add some code
This commit is contained in:
Executable
+14
@@ -0,0 +1,14 @@
|
||||
# For more information about build system see
|
||||
# https://docs.espressif.com/projects/esp-idf/en/latest/api-guides/build-system.html
|
||||
# The following five lines of boilerplate have to be in your project's
|
||||
# CMakeLists in this exact order for cmake to work correctly
|
||||
cmake_minimum_required(VERSION 3.16)
|
||||
|
||||
set(PROJECT_VER "1.9.0")
|
||||
|
||||
# Add this line to disable the specific warning
|
||||
add_compile_options(-Wno-missing-field-initializers)
|
||||
|
||||
include($ENV{IDF_PATH}/tools/cmake/project.cmake)
|
||||
project(xiaozhi)
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2025 Shenzhen Xinzhi Future Technology Co., Ltd.
|
||||
Copyright (c) 2025 Project Contributors
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
@@ -0,0 +1,659 @@
|
||||
dependencies:
|
||||
78/esp-ml307:
|
||||
component_hash: 97a1eeb5274d841bbfbe50ef6b6976f028b0f53e57aee95eda57f49048d02fb9
|
||||
dependencies:
|
||||
- name: idf
|
||||
require: private
|
||||
version: '>=5.3'
|
||||
source:
|
||||
registry_url: https://components.espressif.com/
|
||||
type: service
|
||||
version: 3.3.0
|
||||
78/esp-opus:
|
||||
component_hash: 8182b733f071d7bfe1e837f4c9f8649a63e4c937177f089e65772880c02f2e17
|
||||
dependencies:
|
||||
- name: idf
|
||||
require: private
|
||||
version: '>=5.0'
|
||||
source:
|
||||
registry_url: https://components.espressif.com
|
||||
type: service
|
||||
version: 1.0.5
|
||||
78/esp-opus-encoder:
|
||||
component_hash: b80e5b6d6dc4bf6b0bf1a3729f52b80500e9e6b1003b3e827b78ba738283a296
|
||||
dependencies:
|
||||
- name: 78/esp-opus
|
||||
registry_url: https://components.espressif.com
|
||||
require: private
|
||||
version: ^1.0.5
|
||||
- name: idf
|
||||
require: private
|
||||
version: '>=5.3'
|
||||
source:
|
||||
registry_url: https://components.espressif.com/
|
||||
type: service
|
||||
version: 2.4.1
|
||||
78/esp-wifi-connect:
|
||||
component_hash: 752e62d469a341495368b6a3f812afdbe37569ea5b4460f4eedec42253118e8c
|
||||
dependencies:
|
||||
- name: idf
|
||||
require: private
|
||||
version: '>=5.3'
|
||||
source:
|
||||
registry_url: https://components.espressif.com/
|
||||
type: service
|
||||
version: 2.5.2
|
||||
78/esp_lcd_nv3023:
|
||||
component_hash: fa88abfc19a312eb5e6f2ffa187e0a9faf67e01e758bfb979d3f9d92561a494f
|
||||
dependencies:
|
||||
- name: espressif/cmake_utilities
|
||||
registry_url: https://components.espressif.com
|
||||
require: private
|
||||
version: 0.*
|
||||
- name: idf
|
||||
require: private
|
||||
version: '>=4.4'
|
||||
source:
|
||||
registry_url: https://components.espressif.com/
|
||||
type: service
|
||||
version: 1.0.0
|
||||
78/xiaozhi-fonts:
|
||||
component_hash: d9cc3aad735638e558cee514103b25d2cb60afc78ef53709ffeea443b4d1c835
|
||||
dependencies:
|
||||
- name: idf
|
||||
require: private
|
||||
version: '>=5.3'
|
||||
source:
|
||||
registry_url: https://components.espressif.com/
|
||||
type: service
|
||||
version: 1.5.1
|
||||
chmorgan/esp-libhelix-mp3:
|
||||
component_hash: cbb76089dc2c5749f7b470e2e70aedc44c9da519e04eb9a67d4c7ec275229e53
|
||||
dependencies:
|
||||
- name: idf
|
||||
require: private
|
||||
version: '>=4.1.0'
|
||||
source:
|
||||
registry_url: https://components.espressif.com/
|
||||
type: service
|
||||
version: 1.0.3
|
||||
espressif/adc_battery_estimation:
|
||||
component_hash: a63de81f60adddd5204ed8f286754f1186f16a2fc0f2119152a9d36771f9526a
|
||||
dependencies:
|
||||
- name: espressif/cmake_utilities
|
||||
registry_url: https://components.espressif.com
|
||||
require: private
|
||||
version: '*'
|
||||
- name: idf
|
||||
require: private
|
||||
version: '>=5.0'
|
||||
source:
|
||||
registry_url: https://components.espressif.com/
|
||||
type: service
|
||||
version: 0.2.0
|
||||
espressif/adc_mic:
|
||||
component_hash: ca6ef69bba4dc0d3e0ce53937635ed2734d38ac947881da81b8526e6851a71a4
|
||||
dependencies:
|
||||
- name: espressif/cmake_utilities
|
||||
registry_url: https://components.espressif.com
|
||||
require: private
|
||||
version: '*'
|
||||
- name: espressif/esp_codec_dev
|
||||
registry_url: https://components.espressif.com
|
||||
require: private
|
||||
version: ^1.3.*
|
||||
- name: idf
|
||||
require: private
|
||||
version: '>=5.0'
|
||||
source:
|
||||
registry_url: https://components.espressif.com/
|
||||
type: service
|
||||
version: 0.2.1
|
||||
espressif/button:
|
||||
component_hash: f53face2ab21fa0ffaf4cf0f6e513d393f56df6586bb2ad1146120f03f19ee05
|
||||
dependencies:
|
||||
- name: espressif/cmake_utilities
|
||||
registry_url: https://components.espressif.com
|
||||
require: private
|
||||
version: '*'
|
||||
- name: idf
|
||||
require: private
|
||||
version: '>=4.0'
|
||||
source:
|
||||
registry_url: https://components.espressif.com/
|
||||
type: service
|
||||
version: 4.1.3
|
||||
espressif/cmake_utilities:
|
||||
component_hash: 351350613ceafba240b761b4ea991e0f231ac7a9f59a9ee901f751bddc0bb18f
|
||||
dependencies:
|
||||
- name: idf
|
||||
require: private
|
||||
version: '>=4.1'
|
||||
source:
|
||||
registry_url: https://components.espressif.com
|
||||
type: service
|
||||
version: 0.5.3
|
||||
espressif/dl_fft:
|
||||
component_hash: 7dadbd644c0d7ba4733cc3726ec4cff6edf27b043725e1115861dec1609a3d28
|
||||
dependencies:
|
||||
- name: idf
|
||||
require: private
|
||||
version: '>=5.0'
|
||||
source:
|
||||
registry_url: https://components.espressif.com
|
||||
type: service
|
||||
version: 0.3.1
|
||||
espressif/esp-dsp:
|
||||
component_hash: 619639efc18cfa361a9e423739b9b0ffc14991effc6c027f955c2f2c3bf1754b
|
||||
dependencies:
|
||||
- name: idf
|
||||
require: private
|
||||
version: '>=4.2'
|
||||
source:
|
||||
registry_url: https://components.espressif.com
|
||||
type: service
|
||||
version: 1.6.0
|
||||
espressif/esp-sr:
|
||||
component_hash: 12733d9b4aef5d5e295f35c4671835d605992d00583fcd2f8d21166f62c6b071
|
||||
dependencies:
|
||||
- name: espressif/dl_fft
|
||||
registry_url: https://components.espressif.com
|
||||
require: private
|
||||
version: '>=0.2.0'
|
||||
- name: espressif/esp-dsp
|
||||
registry_url: https://components.espressif.com
|
||||
require: private
|
||||
version: 1.6.0
|
||||
- name: idf
|
||||
require: private
|
||||
version: '>=5.0'
|
||||
source:
|
||||
registry_url: https://components.espressif.com/
|
||||
type: service
|
||||
version: 2.1.5
|
||||
espressif/esp32-camera:
|
||||
component_hash: b209707f12aff1683c5c9dfaff3fa60f0eca687f2bf74f133cdef68fbae86028
|
||||
dependencies:
|
||||
- name: espressif/esp_jpeg
|
||||
registry_url: https://components.espressif.com
|
||||
require: public
|
||||
version: ^1.3.0
|
||||
- name: idf
|
||||
require: private
|
||||
version: '>=5.1'
|
||||
source:
|
||||
registry_url: https://components.espressif.com/
|
||||
type: service
|
||||
version: 2.1.2
|
||||
espressif/esp_codec_dev:
|
||||
component_hash: 3a1df01ee46d64c55155341bb6f4834db33db7dbd9b637e476e1eab64d01295a
|
||||
dependencies:
|
||||
- name: idf
|
||||
require: private
|
||||
version: '>=4.0'
|
||||
source:
|
||||
registry_url: https://components.espressif.com/
|
||||
type: service
|
||||
version: 1.4.0
|
||||
espressif/esp_io_expander:
|
||||
component_hash: fbc0de4082fc7c207dc98a93a0ed83d1a929a4ecee83cc567afb406f3ee6d4a6
|
||||
dependencies:
|
||||
- name: idf
|
||||
require: private
|
||||
version: '>=4.4.2'
|
||||
source:
|
||||
registry_url: https://components.espressif.com
|
||||
type: service
|
||||
version: 1.0.1
|
||||
espressif/esp_io_expander_tca9554:
|
||||
component_hash: 8a9e3a7dbef589a54f814ff22e9121da86bce19d0e1ccffa53f5df6bb346a140
|
||||
dependencies:
|
||||
- name: espressif/esp_io_expander
|
||||
registry_url: https://components.espressif.com
|
||||
require: public
|
||||
version: ^1.0.1
|
||||
- name: idf
|
||||
require: private
|
||||
version: '>=5.2'
|
||||
source:
|
||||
registry_url: https://components.espressif.com/
|
||||
type: service
|
||||
version: 2.0.0
|
||||
espressif/esp_io_expander_tca95xx_16bit:
|
||||
component_hash: f0c87a480d3e341fcfa3f7d00890270da1325a294a7d26ddeb5af5fb3ce8ba54
|
||||
dependencies:
|
||||
- name: espressif/esp_io_expander
|
||||
registry_url: https://components.espressif.com
|
||||
require: public
|
||||
version: ^1.0.1
|
||||
- name: idf
|
||||
require: private
|
||||
version: '>=5.2'
|
||||
source:
|
||||
registry_url: https://components.espressif.com/
|
||||
type: service
|
||||
version: 2.0.0
|
||||
espressif/esp_jpeg:
|
||||
component_hash: defb83669293cbf86d0fa86b475ba5517aceed04ed70db435388c151ab37b5d7
|
||||
dependencies:
|
||||
- name: idf
|
||||
require: private
|
||||
version: '>=5.0'
|
||||
source:
|
||||
registry_url: https://components.espressif.com
|
||||
type: service
|
||||
version: 1.3.1
|
||||
espressif/esp_lcd_axs15231b:
|
||||
component_hash: 654890185757826d1d23925afa4bccf874acd7f15aa6fadca1bc0ef408b2d273
|
||||
dependencies:
|
||||
- name: espressif/cmake_utilities
|
||||
registry_url: https://components.espressif.com
|
||||
require: private
|
||||
version: 0.*
|
||||
- name: espressif/esp_lcd_touch
|
||||
registry_url: https://components.espressif.com
|
||||
require: public
|
||||
version: ^1
|
||||
- name: idf
|
||||
require: private
|
||||
version: '>5.0.4,!=5.1.1'
|
||||
source:
|
||||
registry_url: https://components.espressif.com/
|
||||
type: service
|
||||
version: 1.0.1
|
||||
espressif/esp_lcd_gc9a01:
|
||||
component_hash: 09ddc8f5c9d718a659ffa30a4040e1ae75077e68492c38aec8c2beaaa7b3a9bc
|
||||
dependencies:
|
||||
- name: espressif/cmake_utilities
|
||||
registry_url: https://components.espressif.com
|
||||
require: private
|
||||
version: 0.*
|
||||
- name: idf
|
||||
require: private
|
||||
version: '>=4.4'
|
||||
source:
|
||||
registry_url: https://components.espressif.com/
|
||||
type: service
|
||||
version: 2.0.1
|
||||
espressif/esp_lcd_ili9341:
|
||||
component_hash: 31f1b793aa2110dd2ae071c21ccbff0a4eb20d9a4ee40b6294c0dc0ad9552c4e
|
||||
dependencies:
|
||||
- name: idf
|
||||
require: private
|
||||
version: '>=4.4'
|
||||
- name: espressif/cmake_utilities
|
||||
registry_url: https://components.espressif.com
|
||||
require: private
|
||||
version: 0.*
|
||||
source:
|
||||
registry_url: https://components.espressif.com/
|
||||
type: service
|
||||
version: 1.2.0
|
||||
espressif/esp_lcd_panel_io_additions:
|
||||
component_hash: 213d5c4a3c322a48c9f993d6bc2372206d34af95db34e87a3e02601bdcad7ce8
|
||||
dependencies:
|
||||
- name: idf
|
||||
require: private
|
||||
version: '>=4.4.2'
|
||||
- name: espressif/cmake_utilities
|
||||
registry_url: https://components.espressif.com
|
||||
require: private
|
||||
version: 0.*
|
||||
- name: espressif/esp_io_expander
|
||||
registry_url: https://components.espressif.com
|
||||
require: public
|
||||
version: ^1
|
||||
source:
|
||||
registry_url: https://components.espressif.com/
|
||||
type: service
|
||||
version: 1.0.1
|
||||
espressif/esp_lcd_spd2010:
|
||||
component_hash: 8637c97feeb8d83ba637599f6bf4ef30e83595486930e7df17ffa24f3fef1242
|
||||
dependencies:
|
||||
- name: idf
|
||||
require: private
|
||||
version: '>5.0.4,!=5.1.1'
|
||||
- name: espressif/cmake_utilities
|
||||
registry_url: https://components.espressif.com
|
||||
require: private
|
||||
version: 0.*
|
||||
source:
|
||||
registry_url: https://components.espressif.com/
|
||||
type: service
|
||||
version: 1.0.2
|
||||
espressif/esp_lcd_st77916:
|
||||
component_hash: 5fa0f8b1274576d4484e2b8d9358e2a5d09c721511bef0dce6a55b4206b5f0e9
|
||||
dependencies:
|
||||
- name: espressif/cmake_utilities
|
||||
registry_url: https://components.espressif.com
|
||||
require: private
|
||||
version: 0.*
|
||||
- name: idf
|
||||
require: private
|
||||
version: '>5.0.4,!=5.1.1'
|
||||
source:
|
||||
registry_url: https://components.espressif.com/
|
||||
type: service
|
||||
version: 1.0.1
|
||||
espressif/esp_lcd_st7796:
|
||||
component_hash: 00ab2872c56a4037e6d1efda104ef0da00c5296865f8f938cc7cc2fc3e99f962
|
||||
dependencies:
|
||||
- name: espressif/cmake_utilities
|
||||
registry_url: https://components.espressif.com
|
||||
require: private
|
||||
version: 0.*
|
||||
- name: idf
|
||||
require: private
|
||||
version: '>=4.4'
|
||||
source:
|
||||
registry_url: https://components.espressif.com/
|
||||
type: service
|
||||
targets:
|
||||
- esp32
|
||||
- esp32s2
|
||||
- esp32s3
|
||||
- esp32p4
|
||||
version: 1.3.2
|
||||
espressif/esp_lcd_touch:
|
||||
component_hash: 779b4ba2464a3ae85681e4b860caa5fdc35801458c23f3039ee761bae7f442a4
|
||||
dependencies:
|
||||
- name: idf
|
||||
require: private
|
||||
version: '>=4.4.2'
|
||||
source:
|
||||
registry_url: https://components.espressif.com
|
||||
type: service
|
||||
version: 1.1.2
|
||||
espressif/esp_lcd_touch_cst816s:
|
||||
component_hash: 51dfa9cee38d8a20f4b625d7f89120dff08c8557e613e09dfb31f53d48648235
|
||||
dependencies:
|
||||
- name: espressif/esp_lcd_touch
|
||||
registry_url: https://components.espressif.com
|
||||
require: public
|
||||
version: ^1.0.4
|
||||
- name: idf
|
||||
require: private
|
||||
version: '>=4.4.2'
|
||||
source:
|
||||
registry_url: https://components.espressif.com/
|
||||
type: service
|
||||
version: 1.1.0
|
||||
espressif/esp_lcd_touch_ft5x06:
|
||||
component_hash: abaec05f46a793549b60afdda9eff86e3c8e87782c8c169007911232388d2858
|
||||
dependencies:
|
||||
- name: espressif/esp_lcd_touch
|
||||
registry_url: https://components.espressif.com
|
||||
require: public
|
||||
version: ^1.0.4
|
||||
- name: idf
|
||||
require: private
|
||||
version: '>=4.4.2'
|
||||
source:
|
||||
registry_url: https://components.espressif.com/
|
||||
type: service
|
||||
version: 1.0.7
|
||||
espressif/esp_lcd_touch_gt1151:
|
||||
component_hash: 69dd86cd5fad2442e3bf15c8c4ddddbe9e8739bdb26cd5f2c5249601b4c3cc38
|
||||
dependencies:
|
||||
- name: idf
|
||||
require: private
|
||||
version: '>=4.4.2'
|
||||
- name: espressif/esp_lcd_touch
|
||||
registry_url: https://components.espressif.com
|
||||
require: public
|
||||
version: ^1.0.4
|
||||
source:
|
||||
registry_url: https://components.espressif.com/
|
||||
type: service
|
||||
version: 1.0.5~2
|
||||
espressif/esp_lcd_touch_gt911:
|
||||
component_hash: acc1c184358aa29ef72506f618c9c76a8cc2bf12af38a2bff3d44d84f3a08857
|
||||
dependencies:
|
||||
- name: espressif/esp_lcd_touch
|
||||
registry_url: https://components.espressif.com
|
||||
require: public
|
||||
version: ^1.1.0
|
||||
- name: idf
|
||||
require: private
|
||||
version: '>=4.4.2'
|
||||
source:
|
||||
registry_url: https://components.espressif.com/
|
||||
type: service
|
||||
version: 1.1.3
|
||||
espressif/esp_lvgl_port:
|
||||
component_hash: e720c95cf0667554a204591bb5fade4655fb2990465557041200fa44b5bc7556
|
||||
dependencies:
|
||||
- name: idf
|
||||
require: private
|
||||
version: '>=4.4'
|
||||
- name: lvgl/lvgl
|
||||
registry_url: https://components.espressif.com
|
||||
require: public
|
||||
version: '>=8,<10'
|
||||
source:
|
||||
registry_url: https://components.espressif.com/
|
||||
type: service
|
||||
version: 2.6.0
|
||||
espressif/esp_mmap_assets:
|
||||
component_hash: 9b6eea296488103300f31a9e0fe9096f830b99341332a0dfccd7e3ce43814302
|
||||
dependencies:
|
||||
- name: espressif/cmake_utilities
|
||||
registry_url: https://components.espressif.com
|
||||
require: private
|
||||
version: 0.*
|
||||
- name: idf
|
||||
require: private
|
||||
version: '>=5.0'
|
||||
source:
|
||||
registry_url: https://components.espressif.com/
|
||||
type: service
|
||||
version: 1.3.1~2
|
||||
espressif/esp_new_jpeg:
|
||||
component_hash: 7c07831bbf11d15f84f42dc0e127094c78063b03d0dce688495773656f998d2b
|
||||
dependencies: []
|
||||
source:
|
||||
registry_url: https://components.espressif.com
|
||||
type: service
|
||||
targets:
|
||||
- esp32
|
||||
- esp32s2
|
||||
- esp32s3
|
||||
- esp32p4
|
||||
- esp32c2
|
||||
- esp32c3
|
||||
- esp32c5
|
||||
- esp32c6
|
||||
version: 0.5.1
|
||||
espressif/freetype:
|
||||
component_hash: cd5e2d8458e6e8d73f1120ac474467cabb669d8ea4b25050bf6a348c1e89225e
|
||||
dependencies:
|
||||
- name: idf
|
||||
require: private
|
||||
version: '>=4.4'
|
||||
source:
|
||||
registry_url: https://components.espressif.com
|
||||
type: service
|
||||
version: 2.13.3~1
|
||||
espressif/knob:
|
||||
component_hash: a389d980693ad195b2160de22a72f3391694230188ab16b8f3c7ec4410a7c417
|
||||
dependencies:
|
||||
- name: espressif/cmake_utilities
|
||||
registry_url: https://components.espressif.com
|
||||
require: private
|
||||
version: 0.*
|
||||
- name: idf
|
||||
require: private
|
||||
version: '>=4.4.1'
|
||||
source:
|
||||
registry_url: https://components.espressif.com/
|
||||
type: service
|
||||
version: 1.0.0
|
||||
espressif/led_strip:
|
||||
component_hash: 223998f10cae6d81f2ad2dd3c1103c2221be298c708e37917482b0153f3ec64e
|
||||
dependencies:
|
||||
- name: idf
|
||||
require: private
|
||||
version: '>=5.0'
|
||||
source:
|
||||
registry_url: https://components.espressif.com/
|
||||
type: service
|
||||
version: 3.0.1~1
|
||||
espressif2022/esp_emote_gfx:
|
||||
component_hash: c95160503ccd2ce4c3cf4194888005ca14f0f47a4cd0bb3f6d5f003733a2c3de
|
||||
dependencies:
|
||||
- name: espressif/cmake_utilities
|
||||
registry_url: https://components.espressif.com
|
||||
require: private
|
||||
version: 0.*
|
||||
- name: espressif/esp_new_jpeg
|
||||
registry_url: https://components.espressif.com
|
||||
require: private
|
||||
version: 0.5.*
|
||||
- name: espressif/freetype
|
||||
registry_url: https://components.espressif.com
|
||||
require: private
|
||||
version: 2.*
|
||||
- name: idf
|
||||
require: private
|
||||
version: '>=5.0'
|
||||
source:
|
||||
registry_url: https://components.espressif.com/
|
||||
type: service
|
||||
version: 1.0.0~2
|
||||
espressif2022/image_player:
|
||||
component_hash: 8d09974862ba5323c0c97b77deb3be81ca7bd83e60f77265504c086cd69cc5cf
|
||||
dependencies:
|
||||
- name: espressif/cmake_utilities
|
||||
registry_url: https://components.espressif.com
|
||||
require: private
|
||||
version: 0.*
|
||||
- name: idf
|
||||
require: private
|
||||
version: '>=5.0'
|
||||
source:
|
||||
registry_url: https://components.espressif.com/
|
||||
type: service
|
||||
version: 1.1.0~1
|
||||
idf:
|
||||
source:
|
||||
type: idf
|
||||
version: 5.5.0
|
||||
lvgl/lvgl:
|
||||
component_hash: b702d642e03e95928046d5c6726558e6444e112420c77efa5fdb6650b0a13c5d
|
||||
dependencies: []
|
||||
source:
|
||||
registry_url: https://components.espressif.com/
|
||||
type: service
|
||||
version: 9.3.0
|
||||
tny-robotics/sh1106-esp-idf:
|
||||
component_hash: 7be190d7c58cd635adf8b74b3a841f8245f2f82f36d135a64d8e53cfab39124d
|
||||
dependencies: []
|
||||
source:
|
||||
registry_url: https://components.espressif.com/
|
||||
type: service
|
||||
version: 1.0.0
|
||||
txp666/otto-emoji-gif-component:
|
||||
component_hash: 22580fe159d3fae35f1c44634e883726f503424eb0c96bc1ee9b2cf9e32b6f2f
|
||||
dependencies:
|
||||
- name: idf
|
||||
require: private
|
||||
version: '>=5.4.0'
|
||||
- name: lvgl/lvgl
|
||||
registry_url: https://components.espressif.com
|
||||
require: private
|
||||
version: '>=9.0'
|
||||
source:
|
||||
registry_url: https://components.espressif.com/
|
||||
type: service
|
||||
targets:
|
||||
- esp32s3
|
||||
- esp32
|
||||
- esp32c3
|
||||
- esp32c6
|
||||
- esp32h2
|
||||
- esp32p4
|
||||
version: 1.0.2
|
||||
waveshare/esp_lcd_sh8601:
|
||||
component_hash: 1a2829e9db4e0515bad6ce83368f199dec60519fbba40251d6c8249f5d070ae1
|
||||
dependencies:
|
||||
- name: espressif/cmake_utilities
|
||||
registry_url: https://components.espressif.com
|
||||
require: private
|
||||
version: 0.*
|
||||
- name: idf
|
||||
require: private
|
||||
version: '>=5.3'
|
||||
source:
|
||||
registry_url: https://components.espressif.com/
|
||||
type: service
|
||||
version: 1.0.2
|
||||
waveshare/esp_lcd_touch_cst9217:
|
||||
component_hash: c5da844e73ab7b7e02938901e71f38deed94b26976045fb4517e7fc1e8dc4db5
|
||||
dependencies:
|
||||
- name: espressif/esp_lcd_touch
|
||||
registry_url: https://components.espressif.com
|
||||
require: public
|
||||
version: ^1.1.0
|
||||
- name: idf
|
||||
require: private
|
||||
version: '>=4.4.2'
|
||||
source:
|
||||
registry_url: https://components.espressif.com/
|
||||
type: service
|
||||
version: 1.0.3
|
||||
wvirgil123/sscma_client:
|
||||
component_hash: bf7d4a1f157303f4850d0b9b465c733ce38e8689ff40ac4743a44520524c41d5
|
||||
dependencies:
|
||||
- name: espressif/esp_io_expander
|
||||
registry_url: https://components.espressif.com
|
||||
require: private
|
||||
version: ^1.0.1
|
||||
- name: idf
|
||||
require: private
|
||||
version: '>=4.4.2'
|
||||
source:
|
||||
registry_url: https://components.espressif.com/
|
||||
type: service
|
||||
version: 1.0.2
|
||||
direct_dependencies:
|
||||
- 78/esp-ml307
|
||||
- 78/esp-opus-encoder
|
||||
- 78/esp-wifi-connect
|
||||
- 78/esp_lcd_nv3023
|
||||
- 78/xiaozhi-fonts
|
||||
- chmorgan/esp-libhelix-mp3
|
||||
- espressif/adc_battery_estimation
|
||||
- espressif/adc_mic
|
||||
- espressif/button
|
||||
- espressif/esp-sr
|
||||
- espressif/esp32-camera
|
||||
- espressif/esp_codec_dev
|
||||
- espressif/esp_io_expander_tca9554
|
||||
- espressif/esp_io_expander_tca95xx_16bit
|
||||
- espressif/esp_lcd_axs15231b
|
||||
- espressif/esp_lcd_gc9a01
|
||||
- espressif/esp_lcd_ili9341
|
||||
- espressif/esp_lcd_panel_io_additions
|
||||
- espressif/esp_lcd_spd2010
|
||||
- espressif/esp_lcd_st77916
|
||||
- espressif/esp_lcd_st7796
|
||||
- espressif/esp_lcd_touch_cst816s
|
||||
- espressif/esp_lcd_touch_ft5x06
|
||||
- espressif/esp_lcd_touch_gt1151
|
||||
- espressif/esp_lcd_touch_gt911
|
||||
- espressif/esp_lvgl_port
|
||||
- espressif/esp_mmap_assets
|
||||
- espressif/knob
|
||||
- espressif/led_strip
|
||||
- espressif2022/esp_emote_gfx
|
||||
- espressif2022/image_player
|
||||
- idf
|
||||
- lvgl/lvgl
|
||||
- tny-robotics/sh1106-esp-idf
|
||||
- txp666/otto-emoji-gif-component
|
||||
- waveshare/esp_lcd_sh8601
|
||||
- waveshare/esp_lcd_touch_cst9217
|
||||
- wvirgil123/sscma_client
|
||||
manifest_hash: 1af3184e8179db5dd2d5a0a78e420c425305f4b1d7378a0340ce6fbbffd67c14
|
||||
target: esp32s3
|
||||
version: 2.0.0
|
||||
Vendored
BIN
Binary file not shown.
@@ -0,0 +1,399 @@
|
||||
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"
|
||||
"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"
|
||||
"main.cc"
|
||||
)
|
||||
|
||||
set(INCLUDE_DIRS "." "display" "audio" "protocols")
|
||||
|
||||
# 添加板级公共文件
|
||||
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)
|
||||
|
||||
# 根据 BOARD_TYPE 配置添加对应的板级文件
|
||||
if(CONFIG_BOARD_TYPE_BREAD_COMPACT_WIFI)
|
||||
set(BOARD_TYPE "bread-compact-wifi")
|
||||
elseif(CONFIG_BOARD_TYPE_BREAD_COMPACT_ML307)
|
||||
set(BOARD_TYPE "bread-compact-ml307")
|
||||
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")
|
||||
elseif(CONFIG_BOARD_TYPE_DF_K10)
|
||||
set(BOARD_TYPE "df-k10")
|
||||
elseif(CONFIG_BOARD_TYPE_DF_S3_AI_CAM)
|
||||
set(BOARD_TYPE "df-s3-ai-cam")
|
||||
elseif(CONFIG_BOARD_TYPE_ESP_BOX_3)
|
||||
set(BOARD_TYPE "esp-box-3")
|
||||
elseif(CONFIG_BOARD_TYPE_ESP_BOX)
|
||||
set(BOARD_TYPE "esp-box")
|
||||
elseif(CONFIG_BOARD_TYPE_ESP_BOX_LITE)
|
||||
set(BOARD_TYPE "esp-box-lite")
|
||||
elseif(CONFIG_BOARD_TYPE_KEVIN_BOX_1)
|
||||
set(BOARD_TYPE "kevin-box-1")
|
||||
elseif(CONFIG_BOARD_TYPE_KEVIN_BOX_2)
|
||||
set(BOARD_TYPE "kevin-box-2")
|
||||
elseif(CONFIG_BOARD_TYPE_KEVIN_C3)
|
||||
set(BOARD_TYPE "kevin-c3")
|
||||
elseif(CONFIG_BOARD_TYPE_KEVIN_SP_V3_DEV)
|
||||
set(BOARD_TYPE "kevin-sp-v3-dev")
|
||||
elseif(CONFIG_BOARD_TYPE_KEVIN_SP_V4_DEV)
|
||||
set(BOARD_TYPE "kevin-sp-v4-dev")
|
||||
elseif(CONFIG_BOARD_TYPE_KEVIN_YUYING_313LCD)
|
||||
set(BOARD_TYPE "kevin-yuying-313lcd")
|
||||
elseif(CONFIG_BOARD_TYPE_LICHUANG_DEV)
|
||||
set(BOARD_TYPE "lichuang-dev")
|
||||
elseif(CONFIG_BOARD_TYPE_LICHUANG_C3_DEV)
|
||||
set(BOARD_TYPE "lichuang-c3-dev")
|
||||
elseif(CONFIG_BOARD_TYPE_MAGICLICK_2P4)
|
||||
set(BOARD_TYPE "magiclick-2p4")
|
||||
elseif(CONFIG_BOARD_TYPE_MAGICLICK_2P5)
|
||||
set(BOARD_TYPE "magiclick-2p5")
|
||||
elseif(CONFIG_BOARD_TYPE_MAGICLICK_C3)
|
||||
set(BOARD_TYPE "magiclick-c3")
|
||||
elseif(CONFIG_BOARD_TYPE_MAGICLICK_C3_V2)
|
||||
set(BOARD_TYPE "magiclick-c3-v2")
|
||||
elseif(CONFIG_BOARD_TYPE_M5STACK_CORE_S3)
|
||||
set(BOARD_TYPE "m5stack-core-s3")
|
||||
elseif(CONFIG_BOARD_TYPE_M5STACK_CORE_TAB5)
|
||||
set(BOARD_TYPE "m5stack-tab5")
|
||||
elseif(CONFIG_BOARD_TYPE_ATOMS3_ECHO_BASE)
|
||||
set(BOARD_TYPE "atoms3-echo-base")
|
||||
elseif(CONFIG_BOARD_TYPE_ATOMS3R_ECHO_BASE)
|
||||
set(BOARD_TYPE "atoms3r-echo-base")
|
||||
elseif(CONFIG_BOARD_TYPE_ATOMS3R_CAM_M12_ECHO_BASE)
|
||||
set(BOARD_TYPE "atoms3r-cam-m12-echo-base")
|
||||
elseif(CONFIG_BOARD_TYPE_ATOM_ECHOS3R)
|
||||
set(BOARD_TYPE "atom-echos3r")
|
||||
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")
|
||||
elseif(CONFIG_BOARD_TYPE_XMINI_C3_4G)
|
||||
set(BOARD_TYPE "xmini-c3-4g")
|
||||
elseif(CONFIG_BOARD_TYPE_XMINI_C3)
|
||||
set(BOARD_TYPE "xmini-c3")
|
||||
elseif(CONFIG_BOARD_TYPE_ESP32S3_KORVO2_V3)
|
||||
set(BOARD_TYPE "esp32s3-korvo2-v3")
|
||||
elseif(CONFIG_BOARD_TYPE_ESP_SPARKBOT)
|
||||
set(BOARD_TYPE "esp-sparkbot")
|
||||
elseif(CONFIG_BOARD_TYPE_ESP_SPOT_S3)
|
||||
set(BOARD_TYPE "esp-spot-s3")
|
||||
elseif(CONFIG_BOARD_TYPE_ESP_HI)
|
||||
set(BOARD_TYPE "esp-hi")
|
||||
elseif(CONFIG_BOARD_TYPE_ECHOEAR)
|
||||
set(BOARD_TYPE "echoear")
|
||||
elseif(CONFIG_BOARD_TYPE_ESP32S3_Touch_AMOLED_1_8)
|
||||
set(BOARD_TYPE "esp32-s3-touch-amoled-1.8")
|
||||
elseif(CONFIG_BOARD_TYPE_ESP32S3_Touch_AMOLED_2_06)
|
||||
set(BOARD_TYPE "waveshare-s3-touch-amoled-2.06")
|
||||
elseif(CONFIG_BOARD_TYPE_ESP32S3_Touch_AMOLED_1_75)
|
||||
set(BOARD_TYPE "waveshare-s3-touch-amoled-1.75")
|
||||
elseif(CONFIG_BOARD_TYPE_ESP32S3_Touch_LCD_1_85C)
|
||||
set(BOARD_TYPE "esp32-s3-touch-lcd-1.85c")
|
||||
elseif(CONFIG_BOARD_TYPE_ESP32S3_Touch_LCD_1_85)
|
||||
set(BOARD_TYPE "esp32-s3-touch-lcd-1.85")
|
||||
elseif(CONFIG_BOARD_TYPE_ESP32S3_Touch_LCD_1_46)
|
||||
set(BOARD_TYPE "esp32-s3-touch-lcd-1.46")
|
||||
elseif(CONFIG_BOARD_TYPE_ESP32S3_Touch_LCD_3_5)
|
||||
set(BOARD_TYPE "esp32-s3-touch-lcd-3.5")
|
||||
elseif(CONFIG_BOARD_TYPE_ESP32S3_Touch_LCD_3_5B)
|
||||
set(BOARD_TYPE "waveshare-s3-touch-lcd-3.5b")
|
||||
elseif(CONFIG_BOARD_TYPE_ESP32C6_LCD_1_69)
|
||||
set(BOARD_TYPE "waveshare-c6-lcd-1.69")
|
||||
elseif(CONFIG_BOARD_TYPE_ESP32C6_Touch_AMOLED_1_43)
|
||||
set(BOARD_TYPE "waveshare-c6-touch-amoled-1.43")
|
||||
elseif(CONFIG_BOARD_TYPE_ESP32P4_NANO)
|
||||
set(BOARD_TYPE "waveshare-p4-nano")
|
||||
elseif(CONFIG_BOARD_TYPE_ESP32P4_WIFI6_Touch_LCD_4B)
|
||||
set(BOARD_TYPE "waveshare-p4-wifi6-touch-lcd-4b")
|
||||
elseif(CONFIG_BOARD_TYPE_ESP32P4_WIFI6_Touch_LCD_XC)
|
||||
set(BOARD_TYPE "waveshare-p4-wifi6-touch-lcd-xc")
|
||||
elseif(CONFIG_BOARD_TYPE_BREAD_COMPACT_WIFI_LCD)
|
||||
set(BOARD_TYPE "bread-compact-wifi-lcd")
|
||||
elseif(CONFIG_BOARD_TYPE_TUDOUZI)
|
||||
set(BOARD_TYPE "tudouzi")
|
||||
elseif(CONFIG_BOARD_TYPE_LILYGO_T_CIRCLE_S3)
|
||||
set(BOARD_TYPE "lilygo-t-circle-s3")
|
||||
elseif(CONFIG_BOARD_TYPE_LILYGO_T_CAMERAPLUS_S3_V1_0_V1_1)
|
||||
set(BOARD_TYPE "lilygo-t-cameraplus-s3")
|
||||
elseif(CONFIG_BOARD_TYPE_LILYGO_T_CAMERAPLUS_S3_V1_2)
|
||||
set(BOARD_TYPE "lilygo-t-cameraplus-s3")
|
||||
elseif(CONFIG_BOARD_TYPE_LILYGO_T_DISPLAY_S3_PRO_MVSRLORA)
|
||||
set(BOARD_TYPE "lilygo-t-display-s3-pro-mvsrlora")
|
||||
elseif(CONFIG_BOARD_TYPE_LILYGO_T_DISPLAY_S3_PRO_MVSRLORA_NO_BATTERY)
|
||||
set(BOARD_TYPE "lilygo-t-display-s3-pro-mvsrlora")
|
||||
elseif(CONFIG_BOARD_TYPE_MOVECALL_MOJI_ESP32S3)
|
||||
set(BOARD_TYPE "movecall-moji-esp32s3")
|
||||
elseif(CONFIG_BOARD_TYPE_MOVECALL_CUICAN_ESP32S3)
|
||||
set(BOARD_TYPE "movecall-cuican-esp32s3")
|
||||
elseif(CONFIG_BOARD_TYPE_ATK_DNESP32S3)
|
||||
set(BOARD_TYPE "atk-dnesp32s3")
|
||||
elseif(CONFIG_BOARD_TYPE_ATK_DNESP32S3_BOX)
|
||||
set(BOARD_TYPE "atk-dnesp32s3-box")
|
||||
elseif(CONFIG_BOARD_TYPE_ATK_DNESP32S3_BOX0)
|
||||
set(BOARD_TYPE "atk-dnesp32s3-box0")
|
||||
elseif(CONFIG_BOARD_TYPE_ATK_DNESP32S3_BOX2_WIFI)
|
||||
set(BOARD_TYPE "atk-dnesp32s3-box2-wifi")
|
||||
elseif(CONFIG_BOARD_TYPE_ATK_DNESP32S3_BOX2_4G)
|
||||
set(BOARD_TYPE "atk-dnesp32s3-box2-4g")
|
||||
elseif(CONFIG_BOARD_TYPE_ATK_DNESP32S3M_WIFI)
|
||||
set(BOARD_TYPE "atk-dnesp32s3m-wifi")
|
||||
elseif(CONFIG_BOARD_TYPE_ATK_DNESP32S3M_4G)
|
||||
set(BOARD_TYPE "atk-dnesp32s3m-4g")
|
||||
elseif(CONFIG_BOARD_TYPE_DU_CHATX)
|
||||
set(BOARD_TYPE "du-chatx")
|
||||
elseif(CONFIG_BOARD_TYPE_ESP32S3_Taiji_Pi)
|
||||
set(BOARD_TYPE "taiji-pi-s3")
|
||||
elseif(CONFIG_BOARD_TYPE_XINGZHI_Cube_0_85TFT_WIFI)
|
||||
set(BOARD_TYPE "xingzhi-cube-0.85tft-wifi")
|
||||
elseif(CONFIG_BOARD_TYPE_XINGZHI_Cube_0_85TFT_ML307)
|
||||
set(BOARD_TYPE "xingzhi-cube-0.85tft-ml307")
|
||||
elseif(CONFIG_BOARD_TYPE_XINGZHI_Cube_0_96OLED_WIFI)
|
||||
set(BOARD_TYPE "xingzhi-cube-0.96oled-wifi")
|
||||
elseif(CONFIG_BOARD_TYPE_XINGZHI_Cube_0_96OLED_ML307)
|
||||
set(BOARD_TYPE "xingzhi-cube-0.96oled-ml307")
|
||||
elseif(CONFIG_BOARD_TYPE_XINGZHI_Cube_1_54TFT_WIFI)
|
||||
set(BOARD_TYPE "xingzhi-cube-1.54tft-wifi")
|
||||
elseif(CONFIG_BOARD_TYPE_XINGZHI_Cube_1_54TFT_ML307)
|
||||
set(BOARD_TYPE "xingzhi-cube-1.54tft-ml307")
|
||||
elseif(CONFIG_BOARD_TYPE_SENSECAP_WATCHER)
|
||||
set(BOARD_TYPE "sensecap-watcher")
|
||||
elseif(CONFIG_BOARD_TYPE_DOIT_S3_AIBOX)
|
||||
set(BOARD_TYPE "doit-s3-aibox")
|
||||
elseif(CONFIG_BOARD_TYPE_MIXGO_NOVA)
|
||||
set(BOARD_TYPE "mixgo-nova")
|
||||
elseif(CONFIG_BOARD_TYPE_GENJUTECH_S3_1_54TFT)
|
||||
set(BOARD_TYPE "genjutech-s3-1.54tft")
|
||||
elseif(CONFIG_BOARD_TYPE_ESP32_CGC)
|
||||
set(BOARD_TYPE "esp32-cgc")
|
||||
elseif(CONFIG_BOARD_TYPE_ESP32_CGC_144)
|
||||
set(BOARD_TYPE "esp32-cgc-144")
|
||||
elseif(CONFIG_BOARD_TYPE_ESP_S3_LCD_EV_Board)
|
||||
set(BOARD_TYPE "esp-s3-lcd-ev-board")
|
||||
elseif(CONFIG_BOARD_TYPE_ESP_S3_LCD_EV_Board_2)
|
||||
set(BOARD_TYPE "esp-s3-lcd-ev-board-2")
|
||||
elseif(CONFIG_BOARD_TYPE_ZHENGCHEN_1_54TFT_WIFI)
|
||||
set(BOARD_TYPE "zhengchen-1.54tft-wifi")
|
||||
elseif(CONFIG_BOARD_TYPE_MINSI_K08_DUAL)
|
||||
set(BOARD_TYPE "minsi-k08-dual")
|
||||
elseif(CONFIG_BOARD_TYPE_ZHENGCHEN_1_54TFT_ML307)
|
||||
set(BOARD_TYPE "zhengchen-1.54tft-ml307")
|
||||
elseif(CONFIG_BOARD_TYPE_ESP32_S3_1_54_MUMA)
|
||||
set(BOARD_TYPE "sp-esp32-s3-1.54-muma")
|
||||
elseif(CONFIG_BOARD_TYPE_ESP32_S3_1_28_BOX)
|
||||
set(BOARD_TYPE "sp-esp32-s3-1.28-box")
|
||||
elseif(CONFIG_BOARD_TYPE_OTTO_ROBOT)
|
||||
set(BOARD_TYPE "otto-robot")
|
||||
elseif(CONFIG_BOARD_TYPE_ELECTRON_BOT)
|
||||
set(BOARD_TYPE "electron-bot")
|
||||
elseif(CONFIG_BOARD_TYPE_BREAD_COMPACT_WIFI_CAM)
|
||||
set(BOARD_TYPE "bread-compact-wifi-s3cam")
|
||||
elseif(CONFIG_BOARD_TYPE_JIUCHUAN)
|
||||
set(BOARD_TYPE "jiuchuan-s3")
|
||||
elseif(CONFIG_BOARD_TYPE_LABPLUS_MPYTHON_V3)
|
||||
set(BOARD_TYPE "labplus-mpython-v3")
|
||||
elseif(CONFIG_BOARD_TYPE_LABPLUS_LEDONG_V2)
|
||||
set(BOARD_TYPE "labplus-ledong-v2")
|
||||
elseif(CONFIG_BOARD_TYPE_SURFER_C3_1_14TFT)
|
||||
set(BOARD_TYPE "surfer-c3-1.14tft")
|
||||
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})
|
||||
|
||||
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()
|
||||
|
||||
# 根据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()
|
||||
|
||||
# 定义生成路径
|
||||
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)
|
||||
|
||||
# 如果目标芯片是 ESP32,则排除特定文件
|
||||
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
|
||||
)
|
||||
|
||||
# 使用 target_compile_definitions 来定义 BOARD_TYPE, BOARD_NAME
|
||||
# 如果 BOARD_NAME 为空,则使用 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}\"
|
||||
)
|
||||
|
||||
# 添加生成规则
|
||||
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"
|
||||
)
|
||||
|
||||
# 强制建立生成依赖
|
||||
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}")
|
||||
|
||||
# 检查本地文件是否存在
|
||||
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()
|
||||
@@ -0,0 +1,544 @@
|
||||
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 "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_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_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_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
|
||||
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 LCD_ST7789
|
||||
help
|
||||
屏幕类型选择
|
||||
config LCD_ST7789
|
||||
bool "ST7789, 分辨率240*280"
|
||||
config LCD_ILI9341
|
||||
bool "ILI9341, 分辨率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)
|
||||
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
|
||||
@@ -0,0 +1,869 @@
|
||||
#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 <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;
|
||||
app->OnClockTimer();
|
||||
},
|
||||
.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::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()) {
|
||||
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) + ota.GetFirmwareVersion();
|
||||
display->SetChatMessage("system", message.c_str());
|
||||
|
||||
board.SetPowerSaveMode(false);
|
||||
audio_service_.Stop();
|
||||
vTaskDelay(pdMS_TO_TICKS(1000));
|
||||
|
||||
bool upgrade_success = ota.StartUpgrade([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));
|
||||
// Continue to normal operation (don't break, just fall through)
|
||||
} 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; // This line will never be reached after reboot
|
||||
}
|
||||
}
|
||||
|
||||
// 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 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
|
||||
McpServer::GetInstance().AddCommonTools();
|
||||
|
||||
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();
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
// Print heap stats
|
||||
SystemInfo::PrintHeapStats();
|
||||
}
|
||||
|
||||
void Application::OnClockTimer() {
|
||||
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();
|
||||
}
|
||||
}
|
||||
|
||||
// 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() {
|
||||
// Raise the priority of the main event loop to avoid being interrupted by background tasks (which has priority 2)
|
||||
vTaskPrioritySet(NULL, 3);
|
||||
|
||||
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_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_->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();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
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();
|
||||
|
||||
// 当从idle状态变成其他任何状态时,停止音乐播放
|
||||
if (previous_state == kDeviceStateIdle && state != kDeviceStateIdle) {
|
||||
auto music = board.GetMusic();
|
||||
if (music) {
|
||||
ESP_LOGI(TAG, "Stopping music streaming due to state change: %s -> %s",
|
||||
STATE_STRINGS[previous_state], STATE_STRINGS[state]);
|
||||
music->StopStreaming();
|
||||
}
|
||||
}
|
||||
|
||||
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...");
|
||||
esp_restart();
|
||||
}
|
||||
|
||||
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) {
|
||||
Schedule([this, payload]() {
|
||||
if (protocol_) {
|
||||
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::AddAudioData(AudioStreamPacket&& packet) {
|
||||
auto codec = Board::GetInstance().GetAudioCodec();
|
||||
if (device_state_ == kDeviceStateIdle && codec->output_enabled()) {
|
||||
// packet.payload包含的是原始PCM数据(int16_t)
|
||||
if (packet.payload.size() >= 2) {
|
||||
size_t num_samples = packet.payload.size() / sizeof(int16_t);
|
||||
std::vector<int16_t> pcm_data(num_samples);
|
||||
memcpy(pcm_data.data(), packet.payload.data(), packet.payload.size());
|
||||
|
||||
// 检查采样率是否匹配,如果不匹配则进行简单重采样
|
||||
if (packet.sample_rate != codec->output_sample_rate()) {
|
||||
// ESP_LOGI(TAG, "Resampling music audio from %d to %d Hz",
|
||||
// packet.sample_rate, codec->output_sample_rate());
|
||||
|
||||
// 验证采样率参数
|
||||
if (packet.sample_rate <= 0 || codec->output_sample_rate() <= 0) {
|
||||
ESP_LOGE(TAG, "Invalid sample rates: %d -> %d",
|
||||
packet.sample_rate, codec->output_sample_rate());
|
||||
return;
|
||||
}
|
||||
|
||||
std::vector<int16_t> resampled;
|
||||
|
||||
if (packet.sample_rate > codec->output_sample_rate()) {
|
||||
ESP_LOGI(TAG, "Music playback: Adjust the sampling rate from %d Hz switch to %d Hz",
|
||||
codec->output_sample_rate(), packet.sample_rate);
|
||||
|
||||
// 尝试动态切换采样率
|
||||
if (codec->SetOutputSampleRate(packet.sample_rate)) {
|
||||
ESP_LOGI(TAG, "Successfully switched to music playback sampling rate: %d Hz", packet.sample_rate);
|
||||
} else {
|
||||
ESP_LOGW(TAG, "Unable to switch sampling rate, continue using current sampling rate: %d Hz", codec->output_sample_rate());
|
||||
}
|
||||
} else {
|
||||
// 上采样:线性插值
|
||||
float upsample_ratio = codec->output_sample_rate() / static_cast<float>(packet.sample_rate);
|
||||
size_t expected_size = static_cast<size_t>(pcm_data.size() * upsample_ratio + 0.5f);
|
||||
resampled.reserve(expected_size);
|
||||
|
||||
for (size_t i = 0; i < pcm_data.size(); ++i) {
|
||||
// 添加原始样本
|
||||
resampled.push_back(pcm_data[i]);
|
||||
|
||||
// 计算需要插值的样本数
|
||||
int interpolation_count = static_cast<int>(upsample_ratio) - 1;
|
||||
if (interpolation_count > 0 && i + 1 < pcm_data.size()) {
|
||||
int16_t current = pcm_data[i];
|
||||
int16_t next = pcm_data[i + 1];
|
||||
for (int j = 1; j <= interpolation_count; ++j) {
|
||||
float t = static_cast<float>(j) / (interpolation_count + 1);
|
||||
int16_t interpolated = static_cast<int16_t>(current + (next - current) * t);
|
||||
resampled.push_back(interpolated);
|
||||
}
|
||||
} else if (interpolation_count > 0) {
|
||||
// 最后一个样本,直接重复
|
||||
for (int j = 1; j <= interpolation_count; ++j) {
|
||||
resampled.push_back(pcm_data[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ESP_LOGI(TAG, "Upsampled %d -> %d samples (ratio: %.2f)",
|
||||
pcm_data.size(), resampled.size(), upsample_ratio);
|
||||
}
|
||||
|
||||
pcm_data = std::move(resampled);
|
||||
}
|
||||
|
||||
// 确保音频输出已启用
|
||||
if (!codec->output_enabled()) {
|
||||
codec->EnableOutput(true);
|
||||
}
|
||||
|
||||
// 发送PCM数据到音频编解码器
|
||||
codec->OutputData(pcm_data);
|
||||
|
||||
audio_service_.UpdateOutputTimestamp();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Application::PlaySound(const std::string_view& sound) {
|
||||
audio_service_.PlaySound(sound);
|
||||
}
|
||||
@@ -0,0 +1,93 @@
|
||||
#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)
|
||||
|
||||
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 CanEnterSleepMode();
|
||||
void SendMcpMessage(const std::string& payload);
|
||||
void SetAecMode(AecMode mode);
|
||||
AecMode GetAecMode() const { return aec_mode_; }
|
||||
|
||||
// 新增:接收外部音频数据(如音乐播放)
|
||||
void AddAudioData(AudioStreamPacket&& packet);
|
||||
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;
|
||||
|
||||
void OnWakeWordDetected();
|
||||
void CheckNewVersion(Ota& ota);
|
||||
void ShowActivationCode(const std::string& code, const std::string& message);
|
||||
void OnClockTimer();
|
||||
void SetListeningMode(ListeningMode mode);
|
||||
};
|
||||
|
||||
#endif // _APPLICATION_H_
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -0,0 +1,213 @@
|
||||
// Auto-generated language config
|
||||
// Language: zh-CN with en-US fallback
|
||||
#pragma once
|
||||
|
||||
#include <string_view>
|
||||
|
||||
#ifndef zh_cn
|
||||
#define zh_cn // 預設語言
|
||||
#endif
|
||||
|
||||
namespace Lang {
|
||||
// 语言元数据
|
||||
constexpr const char* CODE = "zh-CN";
|
||||
|
||||
// 字符串资源 (en-US as fallback for missing keys)
|
||||
namespace Strings {
|
||||
constexpr const char* ACCESS_VIA_BROWSER = ",浏览器访问 ";
|
||||
constexpr const char* ACTIVATION = "激活设备";
|
||||
constexpr const char* BATTERY_CHARGING = "正在充电";
|
||||
constexpr const char* BATTERY_FULL = "电量已满";
|
||||
constexpr const char* BATTERY_LOW = "电量不足";
|
||||
constexpr const char* BATTERY_NEED_CHARGE = "电量低,请充电";
|
||||
constexpr const char* CHECKING_NEW_VERSION = "检查新版本...";
|
||||
constexpr const char* CHECK_NEW_VERSION_FAILED = "检查新版本失败,将在 %d 秒后重试:%s";
|
||||
constexpr const char* CONNECTED_TO = "已连接 ";
|
||||
constexpr const char* CONNECTING = "连接中...";
|
||||
constexpr const char* CONNECTION_SUCCESSFUL = "Connection Successful";
|
||||
constexpr const char* CONNECT_TO = "连接 ";
|
||||
constexpr const char* CONNECT_TO_HOTSPOT = "手机连接热点 ";
|
||||
constexpr const char* DETECTING_MODULE = "检测模组...";
|
||||
constexpr const char* ENTERING_WIFI_CONFIG_MODE = "进入配网模式...";
|
||||
constexpr const char* ERROR = "错误";
|
||||
constexpr const char* INFO = "信息";
|
||||
constexpr const char* INITIALIZING = "正在初始化...";
|
||||
constexpr const char* LISTENING = "聆听中...";
|
||||
constexpr const char* LOADING_PROTOCOL = "登录服务器...";
|
||||
constexpr const char* MAX_VOLUME = "最大音量";
|
||||
constexpr const char* MUTED = "已静音";
|
||||
constexpr const char* NEW_VERSION = "新版本 ";
|
||||
constexpr const char* OTA_UPGRADE = "OTA 升级";
|
||||
constexpr const char* PIN_ERROR = "请插入 SIM 卡";
|
||||
constexpr const char* REGISTERING_NETWORK = "等待网络...";
|
||||
constexpr const char* REG_ERROR = "无法接入网络,请检查流量卡状态";
|
||||
constexpr const char* RTC_MODE_OFF = "AEC 关闭";
|
||||
constexpr const char* RTC_MODE_ON = "AEC 开启";
|
||||
constexpr const char* SCANNING_WIFI = "扫描 Wi-Fi...";
|
||||
constexpr const char* SERVER_ERROR = "发送失败,请检查网络";
|
||||
constexpr const char* SERVER_NOT_CONNECTED = "无法连接服务,请稍后再试";
|
||||
constexpr const char* SERVER_NOT_FOUND = "正在寻找可用服务";
|
||||
constexpr const char* SERVER_TIMEOUT = "等待响应超时";
|
||||
constexpr const char* SPEAKING = "说话中...";
|
||||
constexpr const char* STANDBY = "待命";
|
||||
constexpr const char* SWITCH_TO_4G_NETWORK = "切换到 4G...";
|
||||
constexpr const char* SWITCH_TO_WIFI_NETWORK = "切换到 Wi-Fi...";
|
||||
constexpr const char* UPGRADE_FAILED = "升级失败";
|
||||
constexpr const char* UPGRADING = "正在升级系统...";
|
||||
constexpr const char* VERSION = "版本 ";
|
||||
constexpr const char* VOLUME = "音量 ";
|
||||
constexpr const char* WARNING = "警告";
|
||||
constexpr const char* WIFI_CONFIG_MODE = "配网模式";
|
||||
}
|
||||
|
||||
// 音效资源 (en-US as fallback for missing audio files)
|
||||
namespace Sounds {
|
||||
|
||||
extern const char ogg_0_start[] asm("_binary_0_ogg_start");
|
||||
extern const char ogg_0_end[] asm("_binary_0_ogg_end");
|
||||
static const std::string_view OGG_0 {
|
||||
static_cast<const char*>(ogg_0_start),
|
||||
static_cast<size_t>(ogg_0_end - ogg_0_start)
|
||||
};
|
||||
|
||||
extern const char ogg_1_start[] asm("_binary_1_ogg_start");
|
||||
extern const char ogg_1_end[] asm("_binary_1_ogg_end");
|
||||
static const std::string_view OGG_1 {
|
||||
static_cast<const char*>(ogg_1_start),
|
||||
static_cast<size_t>(ogg_1_end - ogg_1_start)
|
||||
};
|
||||
|
||||
extern const char ogg_2_start[] asm("_binary_2_ogg_start");
|
||||
extern const char ogg_2_end[] asm("_binary_2_ogg_end");
|
||||
static const std::string_view OGG_2 {
|
||||
static_cast<const char*>(ogg_2_start),
|
||||
static_cast<size_t>(ogg_2_end - ogg_2_start)
|
||||
};
|
||||
|
||||
extern const char ogg_3_start[] asm("_binary_3_ogg_start");
|
||||
extern const char ogg_3_end[] asm("_binary_3_ogg_end");
|
||||
static const std::string_view OGG_3 {
|
||||
static_cast<const char*>(ogg_3_start),
|
||||
static_cast<size_t>(ogg_3_end - ogg_3_start)
|
||||
};
|
||||
|
||||
extern const char ogg_4_start[] asm("_binary_4_ogg_start");
|
||||
extern const char ogg_4_end[] asm("_binary_4_ogg_end");
|
||||
static const std::string_view OGG_4 {
|
||||
static_cast<const char*>(ogg_4_start),
|
||||
static_cast<size_t>(ogg_4_end - ogg_4_start)
|
||||
};
|
||||
|
||||
extern const char ogg_5_start[] asm("_binary_5_ogg_start");
|
||||
extern const char ogg_5_end[] asm("_binary_5_ogg_end");
|
||||
static const std::string_view OGG_5 {
|
||||
static_cast<const char*>(ogg_5_start),
|
||||
static_cast<size_t>(ogg_5_end - ogg_5_start)
|
||||
};
|
||||
|
||||
extern const char ogg_6_start[] asm("_binary_6_ogg_start");
|
||||
extern const char ogg_6_end[] asm("_binary_6_ogg_end");
|
||||
static const std::string_view OGG_6 {
|
||||
static_cast<const char*>(ogg_6_start),
|
||||
static_cast<size_t>(ogg_6_end - ogg_6_start)
|
||||
};
|
||||
|
||||
extern const char ogg_7_start[] asm("_binary_7_ogg_start");
|
||||
extern const char ogg_7_end[] asm("_binary_7_ogg_end");
|
||||
static const std::string_view OGG_7 {
|
||||
static_cast<const char*>(ogg_7_start),
|
||||
static_cast<size_t>(ogg_7_end - ogg_7_start)
|
||||
};
|
||||
|
||||
extern const char ogg_8_start[] asm("_binary_8_ogg_start");
|
||||
extern const char ogg_8_end[] asm("_binary_8_ogg_end");
|
||||
static const std::string_view OGG_8 {
|
||||
static_cast<const char*>(ogg_8_start),
|
||||
static_cast<size_t>(ogg_8_end - ogg_8_start)
|
||||
};
|
||||
|
||||
extern const char ogg_9_start[] asm("_binary_9_ogg_start");
|
||||
extern const char ogg_9_end[] asm("_binary_9_ogg_end");
|
||||
static const std::string_view OGG_9 {
|
||||
static_cast<const char*>(ogg_9_start),
|
||||
static_cast<size_t>(ogg_9_end - ogg_9_start)
|
||||
};
|
||||
|
||||
extern const char ogg_activation_start[] asm("_binary_activation_ogg_start");
|
||||
extern const char ogg_activation_end[] asm("_binary_activation_ogg_end");
|
||||
static const std::string_view OGG_ACTIVATION {
|
||||
static_cast<const char*>(ogg_activation_start),
|
||||
static_cast<size_t>(ogg_activation_end - ogg_activation_start)
|
||||
};
|
||||
|
||||
extern const char ogg_err_pin_start[] asm("_binary_err_pin_ogg_start");
|
||||
extern const char ogg_err_pin_end[] asm("_binary_err_pin_ogg_end");
|
||||
static const std::string_view OGG_ERR_PIN {
|
||||
static_cast<const char*>(ogg_err_pin_start),
|
||||
static_cast<size_t>(ogg_err_pin_end - ogg_err_pin_start)
|
||||
};
|
||||
|
||||
extern const char ogg_err_reg_start[] asm("_binary_err_reg_ogg_start");
|
||||
extern const char ogg_err_reg_end[] asm("_binary_err_reg_ogg_end");
|
||||
static const std::string_view OGG_ERR_REG {
|
||||
static_cast<const char*>(ogg_err_reg_start),
|
||||
static_cast<size_t>(ogg_err_reg_end - ogg_err_reg_start)
|
||||
};
|
||||
|
||||
extern const char ogg_exclamation_start[] asm("_binary_exclamation_ogg_start");
|
||||
extern const char ogg_exclamation_end[] asm("_binary_exclamation_ogg_end");
|
||||
static const std::string_view OGG_EXCLAMATION {
|
||||
static_cast<const char*>(ogg_exclamation_start),
|
||||
static_cast<size_t>(ogg_exclamation_end - ogg_exclamation_start)
|
||||
};
|
||||
|
||||
extern const char ogg_low_battery_start[] asm("_binary_low_battery_ogg_start");
|
||||
extern const char ogg_low_battery_end[] asm("_binary_low_battery_ogg_end");
|
||||
static const std::string_view OGG_LOW_BATTERY {
|
||||
static_cast<const char*>(ogg_low_battery_start),
|
||||
static_cast<size_t>(ogg_low_battery_end - ogg_low_battery_start)
|
||||
};
|
||||
|
||||
extern const char ogg_popup_start[] asm("_binary_popup_ogg_start");
|
||||
extern const char ogg_popup_end[] asm("_binary_popup_ogg_end");
|
||||
static const std::string_view OGG_POPUP {
|
||||
static_cast<const char*>(ogg_popup_start),
|
||||
static_cast<size_t>(ogg_popup_end - ogg_popup_start)
|
||||
};
|
||||
|
||||
extern const char ogg_success_start[] asm("_binary_success_ogg_start");
|
||||
extern const char ogg_success_end[] asm("_binary_success_ogg_end");
|
||||
static const std::string_view OGG_SUCCESS {
|
||||
static_cast<const char*>(ogg_success_start),
|
||||
static_cast<size_t>(ogg_success_end - ogg_success_start)
|
||||
};
|
||||
|
||||
extern const char ogg_upgrade_start[] asm("_binary_upgrade_ogg_start");
|
||||
extern const char ogg_upgrade_end[] asm("_binary_upgrade_ogg_end");
|
||||
static const std::string_view OGG_UPGRADE {
|
||||
static_cast<const char*>(ogg_upgrade_start),
|
||||
static_cast<size_t>(ogg_upgrade_end - ogg_upgrade_start)
|
||||
};
|
||||
|
||||
extern const char ogg_vibration_start[] asm("_binary_vibration_ogg_start");
|
||||
extern const char ogg_vibration_end[] asm("_binary_vibration_ogg_end");
|
||||
static const std::string_view OGG_VIBRATION {
|
||||
static_cast<const char*>(ogg_vibration_start),
|
||||
static_cast<size_t>(ogg_vibration_end - ogg_vibration_start)
|
||||
};
|
||||
|
||||
extern const char ogg_welcome_start[] asm("_binary_welcome_ogg_start");
|
||||
extern const char ogg_welcome_end[] asm("_binary_welcome_ogg_end");
|
||||
static const std::string_view OGG_WELCOME {
|
||||
static_cast<const char*>(ogg_welcome_start),
|
||||
static_cast<size_t>(ogg_welcome_end - ogg_welcome_start)
|
||||
};
|
||||
|
||||
extern const char ogg_wificonfig_start[] asm("_binary_wificonfig_ogg_start");
|
||||
extern const char ogg_wificonfig_end[] asm("_binary_wificonfig_ogg_end");
|
||||
static const std::string_view OGG_WIFICONFIG {
|
||||
static_cast<const char*>(ogg_wificonfig_start),
|
||||
static_cast<size_t>(ogg_wificonfig_end - ogg_wificonfig_start)
|
||||
};
|
||||
}
|
||||
}
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -0,0 +1,58 @@
|
||||
{
|
||||
"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 مُشغل"
|
||||
}
|
||||
}
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -0,0 +1,58 @@
|
||||
{
|
||||
"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"
|
||||
}
|
||||
}
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -0,0 +1,58 @@
|
||||
{
|
||||
"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"
|
||||
}
|
||||
}
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -0,0 +1,59 @@
|
||||
{
|
||||
"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"
|
||||
}
|
||||
}
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -0,0 +1,58 @@
|
||||
{
|
||||
"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"
|
||||
}
|
||||
}
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
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