mirror of
https://github.com/78/xiaozhi-esp32.git
synced 2026-02-12 07:03:49 +00:00
Compare commits
150 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
6be351b5a0 | ||
|
|
d9447ad060 | ||
|
|
9215a04a7e | ||
|
|
7b7d22c495 | ||
|
|
b4eada876a | ||
|
|
49cd6625f4 | ||
|
|
6f71868bad | ||
|
|
173eaa7463 | ||
|
|
2b025c4ea6 | ||
|
|
37110a9d05 | ||
|
|
796312db4c | ||
|
|
9e1724e892 | ||
|
|
0b3b98eca7 | ||
|
|
abd62648cb | ||
|
|
0883a36537 | ||
|
|
b6c61fe390 | ||
|
|
f7284a57df | ||
|
|
96f34ec70f | ||
|
|
aad2f60b87 | ||
|
|
5b874bc3ad | ||
|
|
7d515a8345 | ||
|
|
d9f7682b2d | ||
|
|
f6ca040d19 | ||
|
|
7ad22d49af | ||
|
|
7fa9056527 | ||
|
|
62b93f986f | ||
|
|
b9617368a0 | ||
|
|
b217cddbd8 | ||
|
|
3a52761d30 | ||
|
|
6b3659c2f5 | ||
|
|
734b5b410a | ||
|
|
d5ec8f7081 | ||
|
|
89674f8838 | ||
|
|
ed51705240 | ||
|
|
c9fa5fabc5 | ||
|
|
e3ed350b8b | ||
|
|
d963e120db | ||
|
|
2ff3796289 | ||
|
|
b48506171b | ||
|
|
7240ea99f1 | ||
|
|
1e8fefbede | ||
|
|
906d819454 | ||
|
|
be88719932 | ||
|
|
213117ded2 | ||
|
|
76ff1cf0dc | ||
|
|
5d44633687 | ||
|
|
5113a5f4bb | ||
|
|
f501a5f440 | ||
|
|
e9649cfc58 | ||
|
|
ee5587019b | ||
|
|
ebdd58748a | ||
|
|
99c32d9331 | ||
|
|
cccaf71c3e | ||
|
|
564018c762 | ||
|
|
0ccdc082b5 | ||
|
|
4b582f8074 | ||
|
|
1f0d2e993b | ||
|
|
b7db68457c | ||
|
|
11c79a7003 | ||
|
|
f9de29519b | ||
|
|
d7c1aef77a | ||
|
|
33c2fe90a8 | ||
|
|
e8f68a331f | ||
|
|
2d15bef298 | ||
|
|
28db4bd60a | ||
|
|
01a12b325f | ||
|
|
c87b1eabf4 | ||
|
|
908c9d5708 | ||
|
|
860d12a12c | ||
|
|
511349a7bd | ||
|
|
764f6e3349 | ||
|
|
59d08c7612 | ||
|
|
ebbb2fa319 | ||
|
|
d984cda486 | ||
|
|
52f3134f30 | ||
|
|
7f332f120c | ||
|
|
ba10b2a2d2 | ||
|
|
92de37e182 | ||
|
|
30970abd1f | ||
|
|
06da25fd26 | ||
|
|
cdb025dd90 | ||
|
|
ce72f196b7 | ||
|
|
4aa47cc591 | ||
|
|
1664fda6e4 | ||
|
|
ccee790c0d | ||
|
|
c6815c7ad5 | ||
|
|
0e51c4c94c | ||
|
|
221d4e7f69 | ||
|
|
bcddbbde26 | ||
|
|
e39a46c1a0 | ||
|
|
1f602fa3a0 | ||
|
|
a9413e2d45 | ||
|
|
6fbc60fa9f | ||
|
|
43ef2f4e7f | ||
|
|
3f54330ac9 | ||
|
|
99a4fc94bf | ||
|
|
c052903ade | ||
|
|
6a4ec9dbbd | ||
|
|
7a85430465 | ||
|
|
e8ed16bb42 | ||
|
|
3176a45ebe | ||
|
|
a601a5cbc1 | ||
|
|
ac03f8097d | ||
|
|
92238612b6 | ||
|
|
c62ab7b239 | ||
|
|
992be9a636 | ||
|
|
60ad1c5afc | ||
|
|
4854bda302 | ||
|
|
1ccd5108c3 | ||
|
|
1d1f9ff1ff | ||
|
|
8373a26f85 | ||
|
|
6a28a98c8b | ||
|
|
549399b795 | ||
|
|
3ee2195340 | ||
|
|
2fd0ff0b2a | ||
|
|
911fee2d85 | ||
|
|
68b0e225a2 | ||
|
|
dd45d0de26 | ||
|
|
916ea39fad | ||
|
|
983d86a334 | ||
|
|
e7fc9ed489 | ||
|
|
e329fcc6b8 | ||
|
|
d3e7fee828 | ||
|
|
96e39bea1b | ||
|
|
a8687f3736 | ||
|
|
8d58bdb21b | ||
|
|
4616fa3486 | ||
|
|
f11f84dfbd | ||
|
|
f418c16b2c | ||
|
|
a1e1f73886 | ||
|
|
d2e99bae34 | ||
|
|
d188415949 | ||
|
|
5018f6c03a | ||
|
|
b413e3ec03 | ||
|
|
fe7ae99a4d | ||
|
|
147d71b9f1 | ||
|
|
384da9fd0f | ||
|
|
ae40f72a39 | ||
|
|
d0ba3a923c | ||
|
|
76c19a0f2d | ||
|
|
f79506d58b | ||
|
|
469ee2d92a | ||
|
|
57c2c64047 | ||
|
|
4048647ef8 | ||
|
|
bce662d135 | ||
|
|
d04b08133f | ||
|
|
897239e997 | ||
|
|
83f6f8c703 | ||
|
|
3a3dfc003e | ||
|
|
fc355605f5 |
126
.clang-format
Normal file
126
.clang-format
Normal file
@@ -0,0 +1,126 @@
|
||||
---
|
||||
Language: Cpp
|
||||
BasedOnStyle: Google
|
||||
AccessModifierOffset: -4
|
||||
AlignAfterOpenBracket: Align
|
||||
AlignConsecutiveAssignments: false
|
||||
AlignConsecutiveDeclarations: false
|
||||
AlignEscapedNewlines: Left
|
||||
AlignOperands: true
|
||||
AlignTrailingComments: true
|
||||
AllowAllParametersOfDeclarationOnNextLine: true
|
||||
AllowShortBlocksOnASingleLine: false
|
||||
AllowShortCaseLabelsOnASingleLine: false
|
||||
AllowShortFunctionsOnASingleLine: All
|
||||
AllowShortIfStatementsOnASingleLine: false
|
||||
AllowShortLoopsOnASingleLine: false
|
||||
AlwaysBreakAfterReturnType: ExceptShortType
|
||||
AlwaysBreakBeforeMultilineStrings: true
|
||||
AlwaysBreakTemplateDeclarations: Yes
|
||||
BinPackArguments: true
|
||||
BinPackParameters: true
|
||||
BraceWrapping:
|
||||
AfterClass: false
|
||||
AfterControlStatement: false
|
||||
AfterEnum: false
|
||||
AfterFunction: false
|
||||
AfterNamespace: false
|
||||
AfterObjCDeclaration: false
|
||||
AfterStruct: false
|
||||
AfterUnion: false
|
||||
AfterExternBlock: false
|
||||
BeforeCatch: false
|
||||
BeforeElse: false
|
||||
IndentBraces: false
|
||||
SplitEmptyFunction: false
|
||||
SplitEmptyRecord: false
|
||||
SplitEmptyNamespace: false
|
||||
BreakBeforeBinaryOperators: None
|
||||
BreakBeforeBraces: Attach
|
||||
BreakBeforeInheritanceComma: false
|
||||
BreakInheritanceList: BeforeColon
|
||||
BreakBeforeTernaryOperators: true
|
||||
BreakConstructorInitializersBeforeComma: false
|
||||
BreakConstructorInitializers: BeforeColon
|
||||
BreakAfterJavaFieldAnnotations: false
|
||||
BreakStringLiterals: true
|
||||
ColumnLimit: 100
|
||||
CommentPragmas: '^ IWYU pragma:'
|
||||
CompactNamespaces: false
|
||||
ConstructorInitializerAllOnOneLineOrOnePerLine: true
|
||||
ConstructorInitializerIndentWidth: 4
|
||||
ContinuationIndentWidth: 4
|
||||
Cpp11BracedListStyle: true
|
||||
DerivePointerAlignment: false
|
||||
DisableFormat: false
|
||||
ExperimentalAutoDetectBinPacking: false
|
||||
FixNamespaceComments: true
|
||||
ForEachMacros:
|
||||
- cJSON_ArrayForEach
|
||||
IncludeBlocks: Preserve
|
||||
IncludeCategories:
|
||||
- Regex: '^<esp_.*\.h>'
|
||||
Priority: 1
|
||||
- Regex: '^<driver/.*\.h>'
|
||||
Priority: 1
|
||||
- Regex: '^<.*\.h>'
|
||||
Priority: 2
|
||||
- Regex: '^<.*'
|
||||
Priority: 3
|
||||
- Regex: '.*'
|
||||
Priority: 4
|
||||
IncludeIsMainRegex: '([-_](test|unittest))?$'
|
||||
IndentCaseLabels: true
|
||||
IndentPPDirectives: None
|
||||
IndentWidth: 4
|
||||
IndentWrappedFunctionNames: false
|
||||
KeepEmptyLinesAtTheStartOfBlocks: false
|
||||
MacroBlockBegin: ''
|
||||
MacroBlockEnd: ''
|
||||
MaxEmptyLinesToKeep: 1
|
||||
NamespaceIndentation: None
|
||||
PenaltyBreakAssignment: 2
|
||||
PenaltyBreakBeforeFirstCallParameter: 1
|
||||
PenaltyBreakComment: 300
|
||||
PenaltyBreakFirstLessLess: 120
|
||||
PenaltyBreakString: 1000
|
||||
PenaltyBreakTemplateDeclaration: 10
|
||||
PenaltyExcessCharacter: 1000000
|
||||
PenaltyReturnTypeOnItsOwnLine: 200
|
||||
PointerAlignment: Left
|
||||
RawStringFormats:
|
||||
- Language: Cpp
|
||||
Delimiters:
|
||||
- cc
|
||||
- CC
|
||||
- cpp
|
||||
- Cpp
|
||||
- CPP
|
||||
- 'c++'
|
||||
- 'C++'
|
||||
CanonicalDelimiter: ''
|
||||
BasedOnStyle: google
|
||||
ReflowComments: true
|
||||
SortIncludes: true
|
||||
SortUsingDeclarations: true
|
||||
SpaceAfterCStyleCast: false
|
||||
SpaceAfterTemplateKeyword: true
|
||||
SpaceBeforeAssignmentOperators: true
|
||||
SpaceBeforeCpp11BracedList: false
|
||||
SpaceBeforeCtorInitializerColon: true
|
||||
SpaceBeforeInheritanceColon: true
|
||||
SpaceBeforeParens: ControlStatements
|
||||
SpaceBeforeRangeBasedForLoopColon: true
|
||||
SpaceInEmptyParentheses: false
|
||||
SpacesBeforeTrailingComments: 2
|
||||
SpacesInAngles: false
|
||||
SpacesInContainerLiterals: true
|
||||
SpacesInCStyleCastParentheses: false
|
||||
SpacesInParentheses: false
|
||||
SpacesInSquareBrackets: false
|
||||
Standard: Latest
|
||||
StatementMacros:
|
||||
- Q_UNUSED
|
||||
- QT_REQUIRE_VERSION
|
||||
TabWidth: 4
|
||||
UseTab: Never
|
||||
51
.github/workflows/build.yml
vendored
51
.github/workflows/build.yml
vendored
@@ -14,10 +14,10 @@ permissions:
|
||||
|
||||
jobs:
|
||||
prepare:
|
||||
name: Determine boards to build
|
||||
name: Determine variants to build
|
||||
runs-on: ubuntu-latest
|
||||
outputs:
|
||||
boards: ${{ steps.select.outputs.boards }}
|
||||
variants: ${{ steps.select.outputs.variants }}
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
@@ -28,30 +28,30 @@ jobs:
|
||||
run: sudo apt-get update && sudo apt-get install -y jq
|
||||
|
||||
- id: list
|
||||
name: Get all board list
|
||||
name: Get all variant list
|
||||
run: |
|
||||
echo "all_boards=$(python scripts/release.py --list-boards --json)" >> $GITHUB_OUTPUT
|
||||
echo "all_variants=$(python scripts/release.py --list-boards --json)" >> $GITHUB_OUTPUT
|
||||
|
||||
- id: select
|
||||
name: Select boards based on changes
|
||||
name: Select variants based on changes
|
||||
env:
|
||||
ALL_BOARDS: ${{ steps.list.outputs.all_boards }}
|
||||
ALL_VARIANTS: ${{ steps.list.outputs.all_variants }}
|
||||
run: |
|
||||
EVENT_NAME="${{ github.event_name }}"
|
||||
|
||||
# For push to main branch, build all boards
|
||||
# push 到 main 分支,编译全部变体
|
||||
if [[ "$EVENT_NAME" == "push" ]]; then
|
||||
echo "boards=$ALL_BOARDS" >> $GITHUB_OUTPUT
|
||||
echo "variants=$ALL_VARIANTS" >> $GITHUB_OUTPUT
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# For pull_request
|
||||
# pull_request 场景
|
||||
BASE_SHA="${{ github.event.pull_request.base.sha }}"
|
||||
HEAD_SHA="${{ github.event.pull_request.head.sha }}"
|
||||
echo "Base: $BASE_SHA, Head: $HEAD_SHA"
|
||||
|
||||
CHANGED=$(git diff --name-only $BASE_SHA $HEAD_SHA || true)
|
||||
echo "Changed files:\n$CHANGED"
|
||||
echo -e "Changed files:\n$CHANGED"
|
||||
|
||||
NEED_ALL=0
|
||||
declare -A AFFECTED
|
||||
@@ -60,6 +60,10 @@ jobs:
|
||||
NEED_ALL=1
|
||||
fi
|
||||
|
||||
if [[ "$file" == main/boards/common/* ]]; then
|
||||
NEED_ALL=1
|
||||
fi
|
||||
|
||||
if [[ "$file" == main/boards/* ]]; then
|
||||
board=$(echo "$file" | cut -d '/' -f3)
|
||||
AFFECTED[$board]=1
|
||||
@@ -67,40 +71,41 @@ jobs:
|
||||
done <<< "$CHANGED"
|
||||
|
||||
if [[ "$NEED_ALL" -eq 1 ]]; then
|
||||
echo "boards=$ALL_BOARDS" >> $GITHUB_OUTPUT
|
||||
echo "variants=$ALL_VARIANTS" >> $GITHUB_OUTPUT
|
||||
else
|
||||
if [[ ${#AFFECTED[@]} -eq 0 ]]; then
|
||||
echo "boards=[]" >> $GITHUB_OUTPUT
|
||||
echo "variants=[]" >> $GITHUB_OUTPUT
|
||||
else
|
||||
JSON=$(printf '%s\n' "${!AFFECTED[@]}" | sort -u | jq -R -s -c 'split("\n")[:-1]')
|
||||
echo "boards=$JSON" >> $GITHUB_OUTPUT
|
||||
BOARDS_JSON=$(printf '%s\n' "${!AFFECTED[@]}" | sort -u | jq -R -s -c 'split("\n")[:-1]')
|
||||
FILTERED=$(echo "$ALL_VARIANTS" | jq -c --argjson boards "$BOARDS_JSON" 'map(select(.board as $b | $boards | index($b)))')
|
||||
echo "variants=$FILTERED" >> $GITHUB_OUTPUT
|
||||
fi
|
||||
fi
|
||||
|
||||
build:
|
||||
name: Build ${{ matrix.board }}
|
||||
name: Build ${{ matrix.name }}
|
||||
needs: prepare
|
||||
if: ${{ needs.prepare.outputs.boards != '[]' }}
|
||||
if: ${{ needs.prepare.outputs.variants != '[]' }}
|
||||
strategy:
|
||||
fail-fast: false # 单个 board 失败不影响其它 board
|
||||
fail-fast: false # 单个变体失败不影响其它变体
|
||||
matrix:
|
||||
board: ${{ fromJson(needs.prepare.outputs.boards) }}
|
||||
include: ${{ fromJson(needs.prepare.outputs.variants) }}
|
||||
runs-on: ubuntu-latest
|
||||
container:
|
||||
image: espressif/idf:release-v5.4
|
||||
image: espressif/idf:v5.5.2
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Build current board
|
||||
- name: Build current variant
|
||||
shell: bash
|
||||
run: |
|
||||
source $IDF_PATH/export.sh
|
||||
python scripts/release.py ${{ matrix.board }}
|
||||
python scripts/release.py ${{ matrix.board }} --name ${{ matrix.name }}
|
||||
|
||||
- name: Upload artifacts
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: xiaozhi_${{ matrix.board }}_${{ github.sha }}.bin
|
||||
name: xiaozhi_${{ matrix.name }}_${{ github.sha }}.bin
|
||||
path: build/merged-binary.bin
|
||||
if-no-files-found: error
|
||||
if-no-files-found: error
|
||||
|
||||
3
.gitignore
vendored
3
.gitignore
vendored
@@ -2,6 +2,7 @@ tmp/
|
||||
components/
|
||||
managed_components/
|
||||
build/
|
||||
dist/
|
||||
.vscode/
|
||||
.devcontainer/
|
||||
sdkconfig.old
|
||||
@@ -13,7 +14,7 @@ main/assets/lang_config.h
|
||||
main/mmap_generate_emoji.h
|
||||
.DS_Store
|
||||
.cache
|
||||
main/mmap_generate_emoji.h
|
||||
*.pyc
|
||||
*.bin
|
||||
mmap_generate_*.h
|
||||
.clangd
|
||||
|
||||
@@ -1,14 +1,13 @@
|
||||
# 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
|
||||
# The following 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)
|
||||
# "Trim" the build. Include the minimal set of components, main, and anything it depends on.
|
||||
idf_build_set_property(MINIMAL_BUILD ON)
|
||||
|
||||
set(PROJECT_VER "2.2.2")
|
||||
project(xiaozhi)
|
||||
|
||||
168
README.md
168
README.md
@@ -1,74 +1,73 @@
|
||||
# An MCP-based Chatbot | 一个基于 MCP 的聊天机器人
|
||||
# An MCP-based Chatbot
|
||||
|
||||
(中文 | [English](README_en.md) | [日本語](README_ja.md))
|
||||
(English | [中文](README_zh.md) | [日本語](README_ja.md))
|
||||
|
||||
## 视频
|
||||
## Introduction
|
||||
|
||||
👉 [人类:给 AI 装摄像头 vs AI:当场发现主人三天没洗头【bilibili】](https://www.bilibili.com/video/BV1bpjgzKEhd/)
|
||||
👉 [Human: Give AI a camera vs AI: Instantly finds out the owner hasn't washed hair for three days【bilibili】](https://www.bilibili.com/video/BV1bpjgzKEhd/)
|
||||
|
||||
👉 [手工打造你的 AI 女友,新手入门教程【bilibili】](https://www.bilibili.com/video/BV1XnmFYLEJN/)
|
||||
👉 [Handcraft your AI girlfriend, beginner's guide【bilibili】](https://www.bilibili.com/video/BV1XnmFYLEJN/)
|
||||
|
||||
## 介绍
|
||||
As a voice interaction entry, the XiaoZhi AI chatbot leverages the AI capabilities of large models like Qwen / DeepSeek, and achieves multi-terminal control via the MCP protocol.
|
||||
|
||||
这是一个由虾哥开源的 ESP32 项目,以 MIT 许可证发布,允许任何人免费使用,或用于商业用途。
|
||||
<img src="docs/mcp-based-graph.jpg" alt="Control everything via MCP" width="320">
|
||||
|
||||
我们希望通过这个项目,能够帮助大家了解 AI 硬件开发,将当下飞速发展的大语言模型应用到实际的硬件设备中。
|
||||
## Version Notes
|
||||
|
||||
如果你有任何想法或建议,请随时提出 Issues 或加入 QQ 群:1011329060
|
||||
The current v2 version is incompatible with the v1 partition table, so it is not possible to upgrade from v1 to v2 via OTA. For partition table details, see [partitions/v2/README.md](partitions/v2/README.md).
|
||||
|
||||
### 基于 MCP 控制万物
|
||||
All hardware running v1 can be upgraded to v2 by manually flashing the firmware.
|
||||
|
||||
小智 AI 聊天机器人作为一个语音交互入口,利用 Qwen / DeepSeek 等大模型的 AI 能力,通过 MCP 协议实现多端控制。
|
||||
The stable version of v1 is 1.9.2. You can switch to v1 by running `git checkout v1`. The v1 branch will be maintained until February 2026.
|
||||
|
||||

|
||||
|
||||
### 已实现功能
|
||||
### Features Implemented
|
||||
|
||||
- Wi-Fi / ML307 Cat.1 4G
|
||||
- 离线语音唤醒 [ESP-SR](https://github.com/espressif/esp-sr)
|
||||
- 支持两种通信协议([Websocket](docs/websocket.md) 或 MQTT+UDP)
|
||||
- 采用 OPUS 音频编解码
|
||||
- 基于流式 ASR + LLM + TTS 架构的语音交互
|
||||
- 声纹识别,识别当前说话人的身份 [3D Speaker](https://github.com/modelscope/3D-Speaker)
|
||||
- OLED / LCD 显示屏,支持表情显示
|
||||
- 电量显示与电源管理
|
||||
- 支持多语言(中文、英文、日文)
|
||||
- 支持 ESP32-C3、ESP32-S3、ESP32-P4 芯片平台
|
||||
- 通过设备端 MCP 实现设备控制(音量、灯光、电机、GPIO 等)
|
||||
- 通过云端 MCP 扩展大模型能力(智能家居控制、PC桌面操作、知识搜索、邮件收发等)
|
||||
- Offline voice wake-up [ESP-SR](https://github.com/espressif/esp-sr)
|
||||
- Supports two communication protocols ([Websocket](docs/websocket.md) or MQTT+UDP)
|
||||
- Uses OPUS audio codec
|
||||
- Voice interaction based on streaming ASR + LLM + TTS architecture
|
||||
- Speaker recognition, identifies the current speaker [3D Speaker](https://github.com/modelscope/3D-Speaker)
|
||||
- OLED / LCD display, supports emoji display
|
||||
- Battery display and power management
|
||||
- Multi-language support (Chinese, English, Japanese)
|
||||
- Supports ESP32-C3, ESP32-S3, ESP32-P4 chip platforms
|
||||
- Device-side MCP for device control (Speaker, LED, Servo, GPIO, etc.)
|
||||
- Cloud-side MCP to extend large model capabilities (smart home control, PC desktop operation, knowledge search, email, etc.)
|
||||
- Customizable wake words, fonts, emojis, and chat backgrounds with online web-based editing ([Custom Assets Generator](https://github.com/78/xiaozhi-assets-generator))
|
||||
|
||||
## 硬件
|
||||
## Hardware
|
||||
|
||||
### 面包板手工制作实践
|
||||
### Breadboard DIY Practice
|
||||
|
||||
详见飞书文档教程:
|
||||
See the Feishu document tutorial:
|
||||
|
||||
👉 [《小智 AI 聊天机器人百科全书》](https://ccnphfhqs21z.feishu.cn/wiki/F5krwD16viZoF0kKkvDcrZNYnhb?from=from_copylink)
|
||||
👉 ["XiaoZhi AI Chatbot Encyclopedia"](https://ccnphfhqs21z.feishu.cn/wiki/F5krwD16viZoF0kKkvDcrZNYnhb?from=from_copylink)
|
||||
|
||||
面包板效果图如下:
|
||||
Breadboard demo:
|
||||
|
||||

|
||||

|
||||
|
||||
### 支持 70 多个开源硬件(仅展示部分)
|
||||
### Supports 70+ Open Source Hardware (Partial List)
|
||||
|
||||
- <a href="https://oshwhub.com/li-chuang-kai-fa-ban/li-chuang-shi-zhan-pai-esp32-s3-kai-fa-ban" target="_blank" title="立创·实战派 ESP32-S3 开发板">立创·实战派 ESP32-S3 开发板</a>
|
||||
- <a href="https://github.com/espressif/esp-box" target="_blank" title="乐鑫 ESP32-S3-BOX3">乐鑫 ESP32-S3-BOX3</a>
|
||||
- <a href="https://oshwhub.com/li-chuang-kai-fa-ban/li-chuang-shi-zhan-pai-esp32-s3-kai-fa-ban" target="_blank" title="LiChuang ESP32-S3 Development Board">LiChuang ESP32-S3 Development Board</a>
|
||||
- <a href="https://github.com/espressif/esp-box" target="_blank" title="Espressif ESP32-S3-BOX3">Espressif ESP32-S3-BOX3</a>
|
||||
- <a href="https://docs.m5stack.com/zh_CN/core/CoreS3" target="_blank" title="M5Stack CoreS3">M5Stack CoreS3</a>
|
||||
- <a href="https://docs.m5stack.com/en/atom/Atomic%20Echo%20Base" target="_blank" title="AtomS3R + Echo Base">M5Stack AtomS3R + Echo Base</a>
|
||||
- <a href="https://gf.bilibili.com/item/detail/1108782064" target="_blank" title="神奇按钮 2.4">神奇按钮 2.4</a>
|
||||
- <a href="https://www.waveshare.net/shop/ESP32-S3-Touch-AMOLED-1.8.htm" target="_blank" title="微雪电子 ESP32-S3-Touch-AMOLED-1.8">微雪电子 ESP32-S3-Touch-AMOLED-1.8</a>
|
||||
- <a href="https://gf.bilibili.com/item/detail/1108782064" target="_blank" title="Magic Button 2.4">Magic Button 2.4</a>
|
||||
- <a href="https://www.waveshare.net/shop/ESP32-S3-Touch-AMOLED-1.8.htm" target="_blank" title="Waveshare ESP32-S3-Touch-AMOLED-1.8">Waveshare ESP32-S3-Touch-AMOLED-1.8</a>
|
||||
- <a href="https://github.com/Xinyuan-LilyGO/T-Circle-S3" target="_blank" title="LILYGO T-Circle-S3">LILYGO T-Circle-S3</a>
|
||||
- <a href="https://oshwhub.com/tenclass01/xmini_c3" target="_blank" title="虾哥 Mini C3">虾哥 Mini C3</a>
|
||||
- <a href="https://oshwhub.com/movecall/cuican-ai-pendant-lights-up-y" target="_blank" title="Movecall CuiCan ESP32S3">璀璨·AI 吊坠</a>
|
||||
- <a href="https://github.com/WMnologo/xingzhi-ai" target="_blank" title="无名科技Nologo-星智-1.54">无名科技 Nologo-星智-1.54TFT</a>
|
||||
- <a href="https://oshwhub.com/tenclass01/xmini_c3" target="_blank" title="XiaGe Mini C3">XiaGe Mini C3</a>
|
||||
- <a href="https://oshwhub.com/movecall/cuican-ai-pendant-lights-up-y" target="_blank" title="Movecall CuiCan ESP32S3">CuiCan AI Pendant</a>
|
||||
- <a href="https://github.com/WMnologo/xingzhi-ai" target="_blank" title="WMnologo-Xingzhi-1.54">WMnologo-Xingzhi-1.54TFT</a>
|
||||
- <a href="https://www.seeedstudio.com/SenseCAP-Watcher-W1-A-p-5979.html" target="_blank" title="SenseCAP Watcher">SenseCAP Watcher</a>
|
||||
- <a href="https://www.bilibili.com/video/BV1BHJtz6E2S/" target="_blank" title="ESP-HI 超低成本机器狗">ESP-HI 超低成本机器狗</a>
|
||||
- <a href="https://www.bilibili.com/video/BV1BHJtz6E2S/" target="_blank" title="ESP-HI Low Cost Robot Dog">ESP-HI Low Cost Robot Dog</a>
|
||||
|
||||
<div style="display: flex; justify-content: space-between;">
|
||||
<a href="docs/v1/lichuang-s3.jpg" target="_blank" title="立创·实战派 ESP32-S3 开发板">
|
||||
<a href="docs/v1/lichuang-s3.jpg" target="_blank" title="LiChuang ESP32-S3 Development Board">
|
||||
<img src="docs/v1/lichuang-s3.jpg" width="240" />
|
||||
</a>
|
||||
<a href="docs/v1/espbox3.jpg" target="_blank" title="乐鑫 ESP32-S3-BOX3">
|
||||
<a href="docs/v1/espbox3.jpg" target="_blank" title="Espressif ESP32-S3-BOX3">
|
||||
<img src="docs/v1/espbox3.jpg" width="240" />
|
||||
</a>
|
||||
<a href="docs/v1/m5cores3.jpg" target="_blank" title="M5Stack CoreS3">
|
||||
@@ -77,78 +76,91 @@
|
||||
<a href="docs/v1/atoms3r.jpg" target="_blank" title="AtomS3R + Echo Base">
|
||||
<img src="docs/v1/atoms3r.jpg" width="240" />
|
||||
</a>
|
||||
<a href="docs/v1/magiclick.jpg" target="_blank" title="神奇按钮 2.4">
|
||||
<a href="docs/v1/magiclick.jpg" target="_blank" title="Magic Button 2.4">
|
||||
<img src="docs/v1/magiclick.jpg" width="240" />
|
||||
</a>
|
||||
<a href="docs/v1/waveshare.jpg" target="_blank" title="微雪电子 ESP32-S3-Touch-AMOLED-1.8">
|
||||
<a href="docs/v1/waveshare.jpg" target="_blank" title="Waveshare ESP32-S3-Touch-AMOLED-1.8">
|
||||
<img src="docs/v1/waveshare.jpg" width="240" />
|
||||
</a>
|
||||
<a href="docs/v1/lilygo-t-circle-s3.jpg" target="_blank" title="LILYGO T-Circle-S3">
|
||||
<img src="docs/v1/lilygo-t-circle-s3.jpg" width="240" />
|
||||
</a>
|
||||
<a href="docs/v1/xmini-c3.jpg" target="_blank" title="虾哥 Mini C3">
|
||||
<a href="docs/v1/xmini-c3.jpg" target="_blank" title="XiaGe Mini C3">
|
||||
<img src="docs/v1/xmini-c3.jpg" width="240" />
|
||||
</a>
|
||||
<a href="docs/v1/movecall-cuican-esp32s3.jpg" target="_blank" title="CuiCan">
|
||||
<img src="docs/v1/movecall-cuican-esp32s3.jpg" width="240" />
|
||||
</a>
|
||||
<a href="docs/v1/wmnologo_xingzhi_1.54.jpg" target="_blank" title="无名科技Nologo-星智-1.54">
|
||||
<a href="docs/v1/wmnologo_xingzhi_1.54.jpg" target="_blank" title="WMnologo-Xingzhi-1.54">
|
||||
<img src="docs/v1/wmnologo_xingzhi_1.54.jpg" width="240" />
|
||||
</a>
|
||||
<a href="docs/v1/sensecap_watcher.jpg" target="_blank" title="SenseCAP Watcher">
|
||||
<img src="docs/v1/sensecap_watcher.jpg" width="240" />
|
||||
</a>
|
||||
<a href="docs/v1/esp-hi.jpg" target="_blank" title="ESP-HI 超低成本机器狗">
|
||||
<a href="docs/v1/esp-hi.jpg" target="_blank" title="ESP-HI Low Cost Robot Dog">
|
||||
<img src="docs/v1/esp-hi.jpg" width="240" />
|
||||
</a>
|
||||
</div>
|
||||
|
||||
## 软件
|
||||
## Software
|
||||
|
||||
### 固件烧录
|
||||
### Firmware Flashing
|
||||
|
||||
新手第一次操作建议先不要搭建开发环境,直接使用免开发环境烧录的固件。
|
||||
For beginners, it is recommended to use the firmware that can be flashed without setting up a development environment.
|
||||
|
||||
固件默认接入 [xiaozhi.me](https://xiaozhi.me) 官方服务器,个人用户注册账号可以免费使用 Qwen 实时模型。
|
||||
The firmware connects to the official [xiaozhi.me](https://xiaozhi.me) server by default. Personal users can register an account to use the Qwen real-time model for free.
|
||||
|
||||
👉 [新手烧录固件教程](https://ccnphfhqs21z.feishu.cn/wiki/Zpz4wXBtdimBrLk25WdcXzxcnNS)
|
||||
👉 [Beginner's Firmware Flashing Guide](https://ccnphfhqs21z.feishu.cn/wiki/Zpz4wXBtdimBrLk25WdcXzxcnNS)
|
||||
|
||||
### 开发环境
|
||||
### Development Environment
|
||||
|
||||
- Cursor 或 VSCode
|
||||
- 安装 ESP-IDF 插件,选择 SDK 版本 5.4 或以上
|
||||
- Linux 比 Windows 更好,编译速度快,也免去驱动问题的困扰
|
||||
- 本项目使用 Google C++ 代码风格,提交代码时请确保符合规范
|
||||
- Cursor or VSCode
|
||||
- Install ESP-IDF plugin, select SDK version 5.4 or above
|
||||
- Linux is better than Windows for faster compilation and fewer driver issues
|
||||
- This project uses Google C++ code style, please ensure compliance when submitting code
|
||||
|
||||
### 开发者文档
|
||||
### Developer Documentation
|
||||
|
||||
- [自定义开发板指南](main/boards/README.md) - 学习如何为小智 AI 创建自定义开发板
|
||||
- [MCP 协议物联网控制用法说明](docs/mcp-usage.md) - 了解如何通过 MCP 协议控制物联网设备
|
||||
- [MCP 协议交互流程](docs/mcp-protocol.md) - 设备端 MCP 协议的实现方式
|
||||
- [MQTT + UDP 混合通信协议文档](docs/mqtt-udp.md)
|
||||
- [一份详细的 WebSocket 通信协议文档](docs/websocket.md)
|
||||
- [Custom Board Guide](docs/custom-board.md) - Learn how to create custom boards for XiaoZhi AI
|
||||
- [MCP Protocol IoT Control Usage](docs/mcp-usage.md) - Learn how to control IoT devices via MCP protocol
|
||||
- [MCP Protocol Interaction Flow](docs/mcp-protocol.md) - Device-side MCP protocol implementation
|
||||
- [MQTT + UDP Hybrid Communication Protocol Document](docs/mqtt-udp.md)
|
||||
- [A detailed WebSocket communication protocol document](docs/websocket.md)
|
||||
|
||||
## 大模型配置
|
||||
## Large Model Configuration
|
||||
|
||||
如果你已经拥有一个小智 AI 聊天机器人设备,并且已接入官方服务器,可以登录 [xiaozhi.me](https://xiaozhi.me) 控制台进行配置。
|
||||
If you already have a XiaoZhi AI chatbot device and have connected to the official server, you can log in to the [xiaozhi.me](https://xiaozhi.me) console for configuration.
|
||||
|
||||
👉 [后台操作视频教程(旧版界面)](https://www.bilibili.com/video/BV1jUCUY2EKM/)
|
||||
👉 [Backend Operation Video Tutorial (Old Interface)](https://www.bilibili.com/video/BV1jUCUY2EKM/)
|
||||
|
||||
## 相关开源项目
|
||||
## Related Open Source Projects
|
||||
|
||||
在个人电脑上部署服务器,可以参考以下第三方开源的项目:
|
||||
For server deployment on personal computers, refer to the following open-source projects:
|
||||
|
||||
- [xinnan-tech/xiaozhi-esp32-server](https://github.com/xinnan-tech/xiaozhi-esp32-server) Python 服务器
|
||||
- [joey-zhou/xiaozhi-esp32-server-java](https://github.com/joey-zhou/xiaozhi-esp32-server-java) Java 服务器
|
||||
- [AnimeAIChat/xiaozhi-server-go](https://github.com/AnimeAIChat/xiaozhi-server-go) Golang 服务器
|
||||
- [xinnan-tech/xiaozhi-esp32-server](https://github.com/xinnan-tech/xiaozhi-esp32-server) Python server
|
||||
- [joey-zhou/xiaozhi-esp32-server-java](https://github.com/joey-zhou/xiaozhi-esp32-server-java) Java server
|
||||
- [AnimeAIChat/xiaozhi-server-go](https://github.com/AnimeAIChat/xiaozhi-server-go) Golang server
|
||||
- [hackers365/xiaozhi-esp32-server-golang](https://github.com/hackers365/xiaozhi-esp32-server-golang) Golang server
|
||||
|
||||
使用小智通信协议的第三方客户端项目:
|
||||
Other client projects using the XiaoZhi communication protocol:
|
||||
|
||||
- [huangjunsen0406/py-xiaozhi](https://github.com/huangjunsen0406/py-xiaozhi) Python 客户端
|
||||
- [TOM88812/xiaozhi-android-client](https://github.com/TOM88812/xiaozhi-android-client) Android 客户端
|
||||
- [100askTeam/xiaozhi-linux](http://github.com/100askTeam/xiaozhi-linux) 百问科技提供的 Linux 客户端
|
||||
- [78/xiaozhi-sf32](https://github.com/78/xiaozhi-sf32) 思澈科技的蓝牙芯片固件
|
||||
- [QuecPython/solution-xiaozhiAI](https://github.com/QuecPython/solution-xiaozhiAI) 移远提供的 QuecPython 固件
|
||||
- [huangjunsen0406/py-xiaozhi](https://github.com/huangjunsen0406/py-xiaozhi) Python client
|
||||
- [TOM88812/xiaozhi-android-client](https://github.com/TOM88812/xiaozhi-android-client) Android client
|
||||
- [100askTeam/xiaozhi-linux](http://github.com/100askTeam/xiaozhi-linux) Linux client by 100ask
|
||||
- [78/xiaozhi-sf32](https://github.com/78/xiaozhi-sf32) Bluetooth chip firmware by Sichuan
|
||||
- [QuecPython/solution-xiaozhiAI](https://github.com/QuecPython/solution-xiaozhiAI) QuecPython firmware by Quectel
|
||||
|
||||
Custom Assets Tools:
|
||||
|
||||
- [78/xiaozhi-assets-generator](https://github.com/78/xiaozhi-assets-generator) Custom Assets Generator (Wake words, fonts, emojis, backgrounds)
|
||||
|
||||
## About the Project
|
||||
|
||||
This is an open-source ESP32 project, released under the MIT license, allowing anyone to use it for free, including for commercial purposes.
|
||||
|
||||
We hope this project helps everyone understand AI hardware development and apply rapidly evolving large language models to real hardware devices.
|
||||
|
||||
If you have any ideas or suggestions, please feel free to raise Issues or join our [Discord](https://discord.gg/bXqgAfRm) or QQ group: 994694848
|
||||
|
||||
## Star History
|
||||
|
||||
@@ -158,4 +170,4 @@
|
||||
<source media="(prefers-color-scheme: light)" srcset="https://api.star-history.com/svg?repos=78/xiaozhi-esp32&type=Date" />
|
||||
<img alt="Star History Chart" src="https://api.star-history.com/svg?repos=78/xiaozhi-esp32&type=Date" />
|
||||
</picture>
|
||||
</a>
|
||||
</a>
|
||||
|
||||
157
README_en.md
157
README_en.md
@@ -1,157 +0,0 @@
|
||||
# An MCP-based Chatbot
|
||||
|
||||
(English | [中文](README.md) | [日本語](README_ja.md))
|
||||
|
||||
## Video
|
||||
|
||||
👉 [Human: Give AI a camera vs AI: Instantly finds out the owner hasn't washed hair for three days【bilibili】](https://www.bilibili.com/video/BV1bpjgzKEhd/)
|
||||
|
||||
👉 [Handcraft your AI girlfriend, beginner's guide【bilibili】](https://www.bilibili.com/video/BV1XnmFYLEJN/)
|
||||
|
||||
## Introduction
|
||||
|
||||
This is an open-source ESP32 project, released under the MIT license, allowing anyone to use it for free, including for commercial purposes.
|
||||
|
||||
We hope this project helps everyone understand AI hardware development and apply rapidly evolving large language models to real hardware devices.
|
||||
|
||||
If you have any ideas or suggestions, please feel free to raise Issues or join the QQ group: 1011329060
|
||||
|
||||
### Control Everything with MCP
|
||||
|
||||
As a voice interaction entry, the XiaoZhi AI chatbot leverages the AI capabilities of large models like Qwen / DeepSeek, and achieves multi-terminal control via the MCP protocol.
|
||||
|
||||

|
||||
|
||||
### Features Implemented
|
||||
|
||||
- Wi-Fi / ML307 Cat.1 4G
|
||||
- Offline voice wake-up [ESP-SR](https://github.com/espressif/esp-sr)
|
||||
- Supports two communication protocols ([Websocket](docs/websocket.md) or MQTT+UDP)
|
||||
- Uses OPUS audio codec
|
||||
- Voice interaction based on streaming ASR + LLM + TTS architecture
|
||||
- Speaker recognition, identifies the current speaker [3D Speaker](https://github.com/modelscope/3D-Speaker)
|
||||
- OLED / LCD display, supports emoji display
|
||||
- Battery display and power management
|
||||
- Multi-language support (Chinese, English, Japanese)
|
||||
- Supports ESP32-C3, ESP32-S3, ESP32-P4 chip platforms
|
||||
- Device-side MCP for device control (Speaker, LED, Servo, GPIO, etc.)
|
||||
- Cloud-side MCP to extend large model capabilities (smart home control, PC desktop operation, knowledge search, email, etc.)
|
||||
|
||||
## Hardware
|
||||
|
||||
### Breadboard DIY Practice
|
||||
|
||||
See the Feishu document tutorial:
|
||||
|
||||
👉 ["XiaoZhi AI Chatbot Encyclopedia"](https://ccnphfhqs21z.feishu.cn/wiki/F5krwD16viZoF0kKkvDcrZNYnhb?from=from_copylink)
|
||||
|
||||
Breadboard demo:
|
||||
|
||||

|
||||
|
||||
### Supports 70+ Open Source Hardware (Partial List)
|
||||
|
||||
- <a href="https://oshwhub.com/li-chuang-kai-fa-ban/li-chuang-shi-zhan-pai-esp32-s3-kai-fa-ban" target="_blank" title="LiChuang ESP32-S3 Development Board">LiChuang ESP32-S3 Development Board</a>
|
||||
- <a href="https://github.com/espressif/esp-box" target="_blank" title="Espressif ESP32-S3-BOX3">Espressif ESP32-S3-BOX3</a>
|
||||
- <a href="https://docs.m5stack.com/zh_CN/core/CoreS3" target="_blank" title="M5Stack CoreS3">M5Stack CoreS3</a>
|
||||
- <a href="https://docs.m5stack.com/en/atom/Atomic%20Echo%20Base" target="_blank" title="AtomS3R + Echo Base">M5Stack AtomS3R + Echo Base</a>
|
||||
- <a href="https://gf.bilibili.com/item/detail/1108782064" target="_blank" title="Magic Button 2.4">Magic Button 2.4</a>
|
||||
- <a href="https://www.waveshare.net/shop/ESP32-S3-Touch-AMOLED-1.8.htm" target="_blank" title="Waveshare ESP32-S3-Touch-AMOLED-1.8">Waveshare ESP32-S3-Touch-AMOLED-1.8</a>
|
||||
- <a href="https://github.com/Xinyuan-LilyGO/T-Circle-S3" target="_blank" title="LILYGO T-Circle-S3">LILYGO T-Circle-S3</a>
|
||||
- <a href="https://oshwhub.com/tenclass01/xmini_c3" target="_blank" title="XiaGe Mini C3">XiaGe Mini C3</a>
|
||||
- <a href="https://oshwhub.com/movecall/cuican-ai-pendant-lights-up-y" target="_blank" title="Movecall CuiCan ESP32S3">CuiCan AI Pendant</a>
|
||||
- <a href="https://github.com/WMnologo/xingzhi-ai" target="_blank" title="WMnologo-Xingzhi-1.54">WMnologo-Xingzhi-1.54TFT</a>
|
||||
- <a href="https://www.seeedstudio.com/SenseCAP-Watcher-W1-A-p-5979.html" target="_blank" title="SenseCAP Watcher">SenseCAP Watcher</a>
|
||||
- <a href="https://www.bilibili.com/video/BV1BHJtz6E2S/" target="_blank" title="ESP-HI Low Cost Robot Dog">ESP-HI Low Cost Robot Dog</a>
|
||||
|
||||
<div style="display: flex; justify-content: space-between;">
|
||||
<a href="docs/v1/lichuang-s3.jpg" target="_blank" title="LiChuang ESP32-S3 Development Board">
|
||||
<img src="docs/v1/lichuang-s3.jpg" width="240" />
|
||||
</a>
|
||||
<a href="docs/v1/espbox3.jpg" target="_blank" title="Espressif ESP32-S3-BOX3">
|
||||
<img src="docs/v1/espbox3.jpg" width="240" />
|
||||
</a>
|
||||
<a href="docs/v1/m5cores3.jpg" target="_blank" title="M5Stack CoreS3">
|
||||
<img src="docs/v1/m5cores3.jpg" width="240" />
|
||||
</a>
|
||||
<a href="docs/v1/atoms3r.jpg" target="_blank" title="AtomS3R + Echo Base">
|
||||
<img src="docs/v1/atoms3r.jpg" width="240" />
|
||||
</a>
|
||||
<a href="docs/v1/magiclick.jpg" target="_blank" title="Magic Button 2.4">
|
||||
<img src="docs/v1/magiclick.jpg" width="240" />
|
||||
</a>
|
||||
<a href="docs/v1/waveshare.jpg" target="_blank" title="Waveshare ESP32-S3-Touch-AMOLED-1.8">
|
||||
<img src="docs/v1/waveshare.jpg" width="240" />
|
||||
</a>
|
||||
<a href="docs/v1/lilygo-t-circle-s3.jpg" target="_blank" title="LILYGO T-Circle-S3">
|
||||
<img src="docs/v1/lilygo-t-circle-s3.jpg" width="240" />
|
||||
</a>
|
||||
<a href="docs/v1/xmini-c3.jpg" target="_blank" title="XiaGe Mini C3">
|
||||
<img src="docs/v1/xmini-c3.jpg" width="240" />
|
||||
</a>
|
||||
<a href="docs/v1/movecall-cuican-esp32s3.jpg" target="_blank" title="CuiCan">
|
||||
<img src="docs/v1/movecall-cuican-esp32s3.jpg" width="240" />
|
||||
</a>
|
||||
<a href="docs/v1/wmnologo_xingzhi_1.54.jpg" target="_blank" title="WMnologo-Xingzhi-1.54">
|
||||
<img src="docs/v1/wmnologo_xingzhi_1.54.jpg" width="240" />
|
||||
</a>
|
||||
<a href="docs/v1/sensecap_watcher.jpg" target="_blank" title="SenseCAP Watcher">
|
||||
<img src="docs/v1/sensecap_watcher.jpg" width="240" />
|
||||
</a>
|
||||
<a href="docs/v1/esp-hi.jpg" target="_blank" title="ESP-HI Low Cost Robot Dog">
|
||||
<img src="docs/v1/esp-hi.jpg" width="240" />
|
||||
</a>
|
||||
</div>
|
||||
|
||||
## Software
|
||||
|
||||
### Firmware Flashing
|
||||
|
||||
For beginners, it is recommended to use the firmware that can be flashed without setting up a development environment.
|
||||
|
||||
The firmware connects to the official [xiaozhi.me](https://xiaozhi.me) server by default. Personal users can register an account to use the Qwen real-time model for free.
|
||||
|
||||
👉 [Beginner's Firmware Flashing Guide](https://ccnphfhqs21z.feishu.cn/wiki/Zpz4wXBtdimBrLk25WdcXzxcnNS)
|
||||
|
||||
### Development Environment
|
||||
|
||||
- Cursor or VSCode
|
||||
- Install ESP-IDF plugin, select SDK version 5.4 or above
|
||||
- Linux is better than Windows for faster compilation and fewer driver issues
|
||||
- This project uses Google C++ code style, please ensure compliance when submitting code
|
||||
|
||||
### Developer Documentation
|
||||
|
||||
- [Custom Board Guide](main/boards/README.md) - Learn how to create custom boards for XiaoZhi AI
|
||||
- [MCP Protocol IoT Control Usage](docs/mcp-usage.md) - Learn how to control IoT devices via MCP protocol
|
||||
- [MCP Protocol Interaction Flow](docs/mcp-protocol.md) - Device-side MCP protocol implementation
|
||||
- [A detailed WebSocket communication protocol document](docs/websocket.md)
|
||||
|
||||
## Large Model Configuration
|
||||
|
||||
If you already have a XiaoZhi AI chatbot device and have connected to the official server, you can log in to the [xiaozhi.me](https://xiaozhi.me) console for configuration.
|
||||
|
||||
👉 [Backend Operation Video Tutorial (Old Interface)](https://www.bilibili.com/video/BV1jUCUY2EKM/)
|
||||
|
||||
## Related Open Source Projects
|
||||
|
||||
For server deployment on personal computers, refer to the following open-source projects:
|
||||
|
||||
- [xinnan-tech/xiaozhi-esp32-server](https://github.com/xinnan-tech/xiaozhi-esp32-server) Python server
|
||||
- [joey-zhou/xiaozhi-esp32-server-java](https://github.com/joey-zhou/xiaozhi-esp32-server-java) Java server
|
||||
- [AnimeAIChat/xiaozhi-server-go](https://github.com/AnimeAIChat/xiaozhi-server-go) Golang server
|
||||
|
||||
Other client projects using the XiaoZhi communication protocol:
|
||||
|
||||
- [huangjunsen0406/py-xiaozhi](https://github.com/huangjunsen0406/py-xiaozhi) Python client
|
||||
- [TOM88812/xiaozhi-android-client](https://github.com/TOM88812/xiaozhi-android-client) Android client
|
||||
|
||||
## Star History
|
||||
|
||||
<a href="https://star-history.com/#78/xiaozhi-esp32&Date">
|
||||
<picture>
|
||||
<source media="(prefers-color-scheme: dark)" srcset="https://api.star-history.com/svg?repos=78/xiaozhi-esp32&type=Date&theme=dark" />
|
||||
<source media="(prefers-color-scheme: light)" srcset="https://api.star-history.com/svg?repos=78/xiaozhi-esp32&type=Date" />
|
||||
<img alt="Star History Chart" src="https://api.star-history.com/svg?repos=78/xiaozhi-esp32&type=Date" />
|
||||
</picture>
|
||||
</a>
|
||||
40
README_ja.md
40
README_ja.md
@@ -1,26 +1,24 @@
|
||||
# MCP ベースのチャットボット
|
||||
|
||||
(日本語 | [中文](README.md) | [English](README_en.md))
|
||||
(日本語 | [中文](README_zh.md) | [English](README.md))
|
||||
|
||||
## 動画
|
||||
## はじめに
|
||||
|
||||
👉 [人間:AIにカメラを装着 vs AI:その場で飼い主が3日間髪を洗っていないことを発見【bilibili】](https://www.bilibili.com/video/BV1bpjgzKEhd/)
|
||||
|
||||
👉 [手作りでAIガールフレンドを作る、初心者入門チュートリアル【bilibili】](https://www.bilibili.com/video/BV1XnmFYLEJN/)
|
||||
|
||||
## イントロダクション
|
||||
|
||||
これはエビ兄さんがオープンソースで公開しているESP32プロジェクトで、MITライセンスのもと、誰でも無料で、商用利用も可能です。
|
||||
|
||||
このプロジェクトを通じて、AIハードウェア開発を理解し、急速に進化する大規模言語モデルを実際のハードウェアデバイスに応用できるようになることを目指しています。
|
||||
|
||||
ご意見やご提案があれば、いつでもIssueを提出するか、QQグループ:1011329060 にご参加ください。
|
||||
|
||||
### MCPであらゆるものを制御
|
||||
|
||||
シャオジーAIチャットボットは音声インタラクションの入口として、Qwen / DeepSeekなどの大規模モデルのAI能力を活用し、MCPプロトコルを通じてマルチエンド制御を実現します。
|
||||
|
||||

|
||||
<img src="docs/mcp-based-graph.jpg" alt="MCPであらゆるものを制御" width="320">
|
||||
|
||||
## バージョンノート
|
||||
|
||||
現在のv2バージョンはv1パーティションテーブルと互換性がないため、v1からv2へOTAでアップグレードすることはできません。パーティションテーブルの詳細については、[partitions/v2/README.md](partitions/v2/README.md)をご参照ください。
|
||||
|
||||
v1を実行しているすべてのハードウェアは、ファームウェアを手動で書き込むことでv2にアップグレードできます。
|
||||
|
||||
v1の安定版は1.9.2です。`git checkout v1`でv1に切り替えることができます。v1ブランチは2026年2月まで継続的にメンテナンスされます。
|
||||
|
||||
### 実装済み機能
|
||||
|
||||
@@ -36,6 +34,7 @@
|
||||
- ESP32-C3、ESP32-S3、ESP32-P4チッププラットフォーム対応
|
||||
- デバイス側MCPによるデバイス制御(音量・明るさ調整、アクション制御など)
|
||||
- クラウド側MCPで大規模モデル能力を拡張(スマートホーム制御、PCデスクトップ操作、知識検索、メール送受信など)
|
||||
- カスタマイズ可能なウェイクワード、フォント、絵文字、チャット背景、オンラインWeb編集に対応 ([カスタムアセットジェネレーター](https://github.com/78/xiaozhi-assets-generator))
|
||||
|
||||
## ハードウェア
|
||||
|
||||
@@ -122,9 +121,10 @@ Feishuドキュメントチュートリアルをご覧ください:
|
||||
|
||||
### 開発者ドキュメント
|
||||
|
||||
- [カスタム開発ボードガイド](main/boards/README.md) - シャオジーAI用のカスタム開発ボード作成方法
|
||||
- [カスタム開発ボードガイド](docs/custom-board.md) - シャオジーAI用のカスタム開発ボード作成方法
|
||||
- [MCPプロトコルIoT制御使用法](docs/mcp-usage.md) - MCPプロトコルでIoTデバイスを制御する方法
|
||||
- [MCPプロトコルインタラクションフロー](docs/mcp-protocol.md) - デバイス側MCPプロトコルの実装方法
|
||||
- [MQTT + UDP ハイブリッド通信プロトコルドキュメント](docs/mqtt-udp.md)
|
||||
- [詳細なWebSocket通信プロトコルドキュメント](docs/websocket.md)
|
||||
|
||||
## 大規模モデル設定
|
||||
@@ -140,11 +140,23 @@ Feishuドキュメントチュートリアルをご覧ください:
|
||||
- [xinnan-tech/xiaozhi-esp32-server](https://github.com/xinnan-tech/xiaozhi-esp32-server) Pythonサーバー
|
||||
- [joey-zhou/xiaozhi-esp32-server-java](https://github.com/joey-zhou/xiaozhi-esp32-server-java) Javaサーバー
|
||||
- [AnimeAIChat/xiaozhi-server-go](https://github.com/AnimeAIChat/xiaozhi-server-go) Golangサーバー
|
||||
- [hackers365/xiaozhi-esp32-server-golang](https://github.com/hackers365/xiaozhi-esp32-server-golang) Golangサーバー
|
||||
|
||||
シャオジー通信プロトコルを利用した他のクライアントプロジェクト:
|
||||
|
||||
- [huangjunsen0406/py-xiaozhi](https://github.com/huangjunsen0406/py-xiaozhi) Pythonクライアント
|
||||
- [TOM88812/xiaozhi-android-client](https://github.com/TOM88812/xiaozhi-android-client) Androidクライアント
|
||||
- [100askTeam/xiaozhi-linux](http://github.com/100askTeam/xiaozhi-linux) 百問科技提供のLinuxクライアント
|
||||
- [78/xiaozhi-sf32](https://github.com/78/xiaozhi-sf32) 思澈科技のBluetoothチップファームウェア
|
||||
- [QuecPython/solution-xiaozhiAI](https://github.com/QuecPython/solution-xiaozhiAI) 移遠提供のQuecPythonファームウェア
|
||||
|
||||
## プロジェクトについて
|
||||
|
||||
これはエビ兄さんがオープンソースで公開しているESP32プロジェクトで、MITライセンスのもと、誰でも無料で、商用利用も可能です。
|
||||
|
||||
このプロジェクトを通じて、AIハードウェア開発を理解し、急速に進化する大規模言語モデルを実際のハードウェアデバイスに応用できるようになることを目指しています。
|
||||
|
||||
ご意見やご提案があれば、いつでもIssueを提出するか、[Discord](https://discord.gg/bXqgAfRm) または QQグループ:1011329060 にご参加ください。
|
||||
|
||||
## スター履歴
|
||||
|
||||
|
||||
169
README_zh.md
Normal file
169
README_zh.md
Normal file
@@ -0,0 +1,169 @@
|
||||
# An MCP-based Chatbot
|
||||
|
||||
(中文 | [English](README.md) | [日本語](README_ja.md))
|
||||
|
||||
## 介绍
|
||||
|
||||
👉 [人类:给 AI 装摄像头 vs AI:当场发现主人三天没洗头【bilibili】](https://www.bilibili.com/video/BV1bpjgzKEhd/)
|
||||
|
||||
👉 [手工打造你的 AI 女友,新手入门教程【bilibili】](https://www.bilibili.com/video/BV1XnmFYLEJN/)
|
||||
|
||||
小智 AI 聊天机器人作为一个语音交互入口,利用 Qwen / DeepSeek 等大模型的 AI 能力,通过 MCP 协议实现多端控制。
|
||||
|
||||
<img src="docs/mcp-based-graph.jpg" alt="通过MCP控制万物" width="320">
|
||||
|
||||
### 版本说明
|
||||
|
||||
当前 v2 版本与 v1 版本分区表不兼容,所以无法从 v1 版本通过 OTA 升级到 v2 版本。分区表说明参见 [partitions/v2/README.md](partitions/v2/README.md)。
|
||||
|
||||
使用 v1 版本的所有硬件,可以通过手动烧录固件来升级到 v2 版本。
|
||||
|
||||
v1 的稳定版本为 1.9.2,可以通过 `git checkout v1` 来切换到 v1 版本,该分支会持续维护到 2026 年 2 月。
|
||||
|
||||
### 已实现功能
|
||||
|
||||
- Wi-Fi / ML307 Cat.1 4G
|
||||
- 离线语音唤醒 [ESP-SR](https://github.com/espressif/esp-sr)
|
||||
- 支持两种通信协议([Websocket](docs/websocket.md) 或 MQTT+UDP)
|
||||
- 采用 OPUS 音频编解码
|
||||
- 基于流式 ASR + LLM + TTS 架构的语音交互
|
||||
- 声纹识别,识别当前说话人的身份 [3D Speaker](https://github.com/modelscope/3D-Speaker)
|
||||
- OLED / LCD 显示屏,支持表情显示
|
||||
- 电量显示与电源管理
|
||||
- 支持多语言(中文、英文、日文)
|
||||
- 支持 ESP32-C3、ESP32-S3、ESP32-P4 芯片平台
|
||||
- 通过设备端 MCP 实现设备控制(音量、灯光、电机、GPIO 等)
|
||||
- 通过云端 MCP 扩展大模型能力(智能家居控制、PC桌面操作、知识搜索、邮件收发等)
|
||||
- 自定义唤醒词、字体、表情与聊天背景,支持网页端在线修改 ([自定义Assets生成器](https://github.com/78/xiaozhi-assets-generator))
|
||||
|
||||
## 硬件
|
||||
|
||||
### 面包板手工制作实践
|
||||
|
||||
详见飞书文档教程:
|
||||
|
||||
👉 [《小智 AI 聊天机器人百科全书》](https://ccnphfhqs21z.feishu.cn/wiki/F5krwD16viZoF0kKkvDcrZNYnhb?from=from_copylink)
|
||||
|
||||
面包板效果图如下:
|
||||
|
||||

|
||||
|
||||
### 支持 70 多个开源硬件(仅展示部分)
|
||||
|
||||
- <a href="https://oshwhub.com/li-chuang-kai-fa-ban/li-chuang-shi-zhan-pai-esp32-s3-kai-fa-ban" target="_blank" title="立创·实战派 ESP32-S3 开发板">立创·实战派 ESP32-S3 开发板</a>
|
||||
- <a href="https://github.com/espressif/esp-box" target="_blank" title="乐鑫 ESP32-S3-BOX3">乐鑫 ESP32-S3-BOX3</a>
|
||||
- <a href="https://docs.m5stack.com/zh_CN/core/CoreS3" target="_blank" title="M5Stack CoreS3">M5Stack CoreS3</a>
|
||||
- <a href="https://docs.m5stack.com/en/atom/Atomic%20Echo%20Base" target="_blank" title="AtomS3R + Echo Base">M5Stack AtomS3R + Echo Base</a>
|
||||
- <a href="https://gf.bilibili.com/item/detail/1108782064" target="_blank" title="神奇按钮 2.4">神奇按钮 2.4</a>
|
||||
- <a href="https://www.waveshare.net/shop/ESP32-S3-Touch-AMOLED-1.8.htm" target="_blank" title="微雪电子 ESP32-S3-Touch-AMOLED-1.8">微雪电子 ESP32-S3-Touch-AMOLED-1.8</a>
|
||||
- <a href="https://github.com/Xinyuan-LilyGO/T-Circle-S3" target="_blank" title="LILYGO T-Circle-S3">LILYGO T-Circle-S3</a>
|
||||
- <a href="https://oshwhub.com/tenclass01/xmini_c3" target="_blank" title="虾哥 Mini C3">虾哥 Mini C3</a>
|
||||
- <a href="https://oshwhub.com/movecall/cuican-ai-pendant-lights-up-y" target="_blank" title="Movecall CuiCan ESP32S3">璀璨·AI 吊坠</a>
|
||||
- <a href="https://github.com/WMnologo/xingzhi-ai" target="_blank" title="无名科技Nologo-星智-1.54">无名科技 Nologo-星智-1.54TFT</a>
|
||||
- <a href="https://www.seeedstudio.com/SenseCAP-Watcher-W1-A-p-5979.html" target="_blank" title="SenseCAP Watcher">SenseCAP Watcher</a>
|
||||
- <a href="https://www.bilibili.com/video/BV1BHJtz6E2S/" target="_blank" title="ESP-HI 超低成本机器狗">ESP-HI 超低成本机器狗</a>
|
||||
|
||||
<div style="display: flex; justify-content: space-between;">
|
||||
<a href="docs/v1/lichuang-s3.jpg" target="_blank" title="立创·实战派 ESP32-S3 开发板">
|
||||
<img src="docs/v1/lichuang-s3.jpg" width="240" />
|
||||
</a>
|
||||
<a href="docs/v1/espbox3.jpg" target="_blank" title="乐鑫 ESP32-S3-BOX3">
|
||||
<img src="docs/v1/espbox3.jpg" width="240" />
|
||||
</a>
|
||||
<a href="docs/v1/m5cores3.jpg" target="_blank" title="M5Stack CoreS3">
|
||||
<img src="docs/v1/m5cores3.jpg" width="240" />
|
||||
</a>
|
||||
<a href="docs/v1/atoms3r.jpg" target="_blank" title="AtomS3R + Echo Base">
|
||||
<img src="docs/v1/atoms3r.jpg" width="240" />
|
||||
</a>
|
||||
<a href="docs/v1/magiclick.jpg" target="_blank" title="神奇按钮 2.4">
|
||||
<img src="docs/v1/magiclick.jpg" width="240" />
|
||||
</a>
|
||||
<a href="docs/v1/waveshare.jpg" target="_blank" title="微雪电子 ESP32-S3-Touch-AMOLED-1.8">
|
||||
<img src="docs/v1/waveshare.jpg" width="240" />
|
||||
</a>
|
||||
<a href="docs/v1/lilygo-t-circle-s3.jpg" target="_blank" title="LILYGO T-Circle-S3">
|
||||
<img src="docs/v1/lilygo-t-circle-s3.jpg" width="240" />
|
||||
</a>
|
||||
<a href="docs/v1/xmini-c3.jpg" target="_blank" title="虾哥 Mini C3">
|
||||
<img src="docs/v1/xmini-c3.jpg" width="240" />
|
||||
</a>
|
||||
<a href="docs/v1/movecall-cuican-esp32s3.jpg" target="_blank" title="CuiCan">
|
||||
<img src="docs/v1/movecall-cuican-esp32s3.jpg" width="240" />
|
||||
</a>
|
||||
<a href="docs/v1/wmnologo_xingzhi_1.54.jpg" target="_blank" title="无名科技Nologo-星智-1.54">
|
||||
<img src="docs/v1/wmnologo_xingzhi_1.54.jpg" width="240" />
|
||||
</a>
|
||||
<a href="docs/v1/sensecap_watcher.jpg" target="_blank" title="SenseCAP Watcher">
|
||||
<img src="docs/v1/sensecap_watcher.jpg" width="240" />
|
||||
</a>
|
||||
<a href="docs/v1/esp-hi.jpg" target="_blank" title="ESP-HI 超低成本机器狗">
|
||||
<img src="docs/v1/esp-hi.jpg" width="240" />
|
||||
</a>
|
||||
</div>
|
||||
|
||||
## 软件
|
||||
|
||||
### 固件烧录
|
||||
|
||||
新手第一次操作建议先不要搭建开发环境,直接使用免开发环境烧录的固件。
|
||||
|
||||
固件默认接入 [xiaozhi.me](https://xiaozhi.me) 官方服务器,个人用户注册账号可以免费使用 Qwen 实时模型。
|
||||
|
||||
👉 [新手烧录固件教程](https://ccnphfhqs21z.feishu.cn/wiki/Zpz4wXBtdimBrLk25WdcXzxcnNS)
|
||||
|
||||
### 开发环境
|
||||
|
||||
- Cursor 或 VSCode
|
||||
- 安装 ESP-IDF 插件,选择 SDK 版本 5.4 或以上
|
||||
- Linux 比 Windows 更好,编译速度快,也免去驱动问题的困扰
|
||||
- 本项目使用 Google C++ 代码风格,提交代码时请确保符合规范
|
||||
|
||||
### 开发者文档
|
||||
|
||||
- [自定义开发板指南](docs/custom-board.md) - 学习如何为小智 AI 创建自定义开发板
|
||||
- [MCP 协议物联网控制用法说明](docs/mcp-usage.md) - 了解如何通过 MCP 协议控制物联网设备
|
||||
- [MCP 协议交互流程](docs/mcp-protocol.md) - 设备端 MCP 协议的实现方式
|
||||
- [MQTT + UDP 混合通信协议文档](docs/mqtt-udp.md)
|
||||
- [一份详细的 WebSocket 通信协议文档](docs/websocket.md)
|
||||
|
||||
## 大模型配置
|
||||
|
||||
如果你已经拥有一个小智 AI 聊天机器人设备,并且已接入官方服务器,可以登录 [xiaozhi.me](https://xiaozhi.me) 控制台进行配置。
|
||||
|
||||
👉 [后台操作视频教程(旧版界面)](https://www.bilibili.com/video/BV1jUCUY2EKM/)
|
||||
|
||||
## 相关开源项目
|
||||
|
||||
在个人电脑上部署服务器,可以参考以下第三方开源的项目:
|
||||
|
||||
- [xinnan-tech/xiaozhi-esp32-server](https://github.com/xinnan-tech/xiaozhi-esp32-server) Python 服务器
|
||||
- [joey-zhou/xiaozhi-esp32-server-java](https://github.com/joey-zhou/xiaozhi-esp32-server-java) Java 服务器
|
||||
- [AnimeAIChat/xiaozhi-server-go](https://github.com/AnimeAIChat/xiaozhi-server-go) Golang 服务器
|
||||
- [hackers365/xiaozhi-esp32-server-golang](https://github.com/hackers365/xiaozhi-esp32-server-golang) Golang 服务器
|
||||
|
||||
使用小智通信协议的第三方客户端项目:
|
||||
|
||||
- [huangjunsen0406/py-xiaozhi](https://github.com/huangjunsen0406/py-xiaozhi) Python 客户端
|
||||
- [TOM88812/xiaozhi-android-client](https://github.com/TOM88812/xiaozhi-android-client) Android 客户端
|
||||
- [100askTeam/xiaozhi-linux](http://github.com/100askTeam/xiaozhi-linux) 百问科技提供的 Linux 客户端
|
||||
- [78/xiaozhi-sf32](https://github.com/78/xiaozhi-sf32) 思澈科技的蓝牙芯片固件
|
||||
- [QuecPython/solution-xiaozhiAI](https://github.com/QuecPython/solution-xiaozhiAI) 移远提供的 QuecPython 固件
|
||||
|
||||
## 关于项目
|
||||
|
||||
这是一个由虾哥开源的 ESP32 项目,以 MIT 许可证发布,允许任何人免费使用,修改或用于商业用途。
|
||||
|
||||
我们希望通过这个项目,能够帮助大家了解 AI 硬件开发,将当下飞速发展的大语言模型应用到实际的硬件设备中。
|
||||
|
||||
如果你有任何想法或建议,请随时提出 Issues 或加入 [Discord](https://discord.gg/bXqgAfRm) 或 QQ 群:1011329060
|
||||
|
||||
## Star History
|
||||
|
||||
<a href="https://star-history.com/#78/xiaozhi-esp32&Date">
|
||||
<picture>
|
||||
<source media="(prefers-color-scheme: dark)" srcset="https://api.star-history.com/svg?repos=78/xiaozhi-esp32&type=Date&theme=dark" />
|
||||
<source media="(prefers-color-scheme: light)" srcset="https://api.star-history.com/svg?repos=78/xiaozhi-esp32&type=Date" />
|
||||
<img alt="Star History Chart" src="https://api.star-history.com/svg?repos=78/xiaozhi-esp32&type=Date" />
|
||||
</picture>
|
||||
</a>
|
||||
1
_codeql_detected_source_root
Symbolic link
1
_codeql_detected_source_root
Symbolic link
@@ -0,0 +1 @@
|
||||
.
|
||||
37
docs/blufi.md
Normal file
37
docs/blufi.md
Normal file
@@ -0,0 +1,37 @@
|
||||
# BluFi 配网(集成 esp-wifi-connect)
|
||||
|
||||
本文档说明如何在小智固件中启用和使用 BluFi(BLE Wi‑Fi 配网),并结合项目内置的 `esp-wifi-connect` 组件完成 Wi‑Fi 连接与存储。官方
|
||||
BluFi
|
||||
协议说明请参考 [Espressif 文档](https://docs.espressif.com/projects/esp-idf/zh_CN/stable/esp32/api-guides/ble/blufi.html)。
|
||||
|
||||
## 前置条件
|
||||
|
||||
- 需要支持 BLE 的芯片与固件配置。
|
||||
- 在 `idf.py menuconfig` 中启用 `WiFi Configuration Method -> Esp Blufi`(`CONFIG_USE_ESP_BLUFI_WIFI_PROVISIONING=y`
|
||||
)。如果想使用 BluFi,必须关闭同一菜单下的 Hotspot 选项,否则默认使用 Hotspot 配网模式。
|
||||
|
||||
- 保持默认的 NVS 与事件循环初始化(项目的 `app_main` 已处理)。
|
||||
- CONFIG_BT_BLUEDROID_ENABLED、CONFIG_BT_NIMBLE_ENABLED这两个宏应二选一,不能同时启用。
|
||||
## 工作流程
|
||||
|
||||
1) 手机端通过 BluFi(如官方 EspBlufi App 或自研客户端)连接设备,发送 Wi‑Fi SSID/密码,手机端可以通过blufi协议获取设备端扫描到的WiFi列表。
|
||||
2) 设备侧在 `ESP_BLUFI_EVENT_REQ_CONNECT_TO_AP` 中将凭据写入 `SsidManager`(存储到 NVS,属于 `esp-wifi-connect` 组件)。
|
||||
3) 随后启动 `WifiStation` 扫描并连接;状态通过 BluFi 返回。
|
||||
4) 配网成功后设备会自动连接新 Wi‑Fi;失败则返回失败状态。
|
||||
|
||||
## 使用步骤
|
||||
|
||||
1. 配置:在 menuconfig 开启 `Esp Blufi`。编译并烧录固件。
|
||||
2. 触发配网:设备首次启动且没有已保存的 Wi‑Fi 时会自动进入配网。
|
||||
3. 手机端操作:打开 EspBlufi App(或其他 BluFi 客户端),搜索并连接设备,可以选择是否加密,按提示输入 Wi‑Fi SSID/密码并发送。
|
||||
4. 观察结果:
|
||||
- 成功:BluFi 报告连接成功,设备自动连接 Wi‑Fi。
|
||||
- 失败:BluFi 返回失败状态,可重新发送或检查路由器。
|
||||
|
||||
## 注意事项
|
||||
|
||||
- BluFi 配网不支持与热点配网同时开启。如果热点配网已经启动,则默认使用热点配网。请在 menuconfig 中只保留一种配网方式。
|
||||
- 若多次测试,建议清除或覆盖存储的 SSID(`wifi` 命名空间),避免旧配置干扰。
|
||||
- 如果使用自定义 BluFi 客户端,需遵循官方协议帧格式,参考上文官方文档链接。
|
||||
- 官方文档中已提供EspBlufi APP下载地址
|
||||
- 由于IDF5.5.2的blufi接口发生变化,5.5.2版本编译后蓝牙名称为"Xiaozhi-Blufi",5.5.1版本中蓝牙名称为"BLUFI_DEVICE"
|
||||
91
docs/code_style.md
Normal file
91
docs/code_style.md
Normal file
@@ -0,0 +1,91 @@
|
||||
# 代码风格指南
|
||||
|
||||
## 代码格式化工具
|
||||
|
||||
本项目使用 clang-format 工具来统一代码风格。我们已经在项目根目录下提供了 `.clang-format` 配置文件,该配置基于 Google C++ 风格指南,并做了一些自定义调整。
|
||||
|
||||
### 安装 clang-format
|
||||
|
||||
在使用之前,请确保你已经安装了 clang-format 工具:
|
||||
|
||||
- **Windows**:
|
||||
```powershell
|
||||
winget install LLVM
|
||||
# 或者使用 Chocolatey
|
||||
choco install llvm
|
||||
```
|
||||
|
||||
- **Linux**:
|
||||
```bash
|
||||
sudo apt install clang-format # Ubuntu/Debian
|
||||
sudo dnf install clang-tools-extra # Fedora
|
||||
```
|
||||
|
||||
- **macOS**:
|
||||
```bash
|
||||
brew install clang-format
|
||||
```
|
||||
|
||||
### 使用方法
|
||||
|
||||
1. **格式化单个文件**:
|
||||
```bash
|
||||
clang-format -i path/to/your/file.cpp
|
||||
```
|
||||
|
||||
2. **格式化整个项目**:
|
||||
```bash
|
||||
# 在项目根目录下执行
|
||||
find main -iname *.h -o -iname *.cc | xargs clang-format -i
|
||||
```
|
||||
|
||||
3. **在提交代码前检查格式**:
|
||||
```bash
|
||||
# 检查文件格式是否符合规范(不修改文件)
|
||||
clang-format --dry-run -Werror path/to/your/file.cpp
|
||||
```
|
||||
|
||||
### IDE 集成
|
||||
|
||||
- **Visual Studio Code**:
|
||||
1. 安装 C/C++ 扩展
|
||||
2. 在设置中启用 `C_Cpp.formatting` 为 `clang-format`
|
||||
3. 可以设置保存时自动格式化:`editor.formatOnSave: true`
|
||||
|
||||
- **CLion**:
|
||||
1. 在设置中选择 `Editor > Code Style > C/C++`
|
||||
2. 将 `Formatter` 设置为 `clang-format`
|
||||
3. 选择使用项目中的 `.clang-format` 配置文件
|
||||
|
||||
### 主要格式规则
|
||||
|
||||
- 缩进使用 4 个空格
|
||||
- 行宽限制为 100 字符
|
||||
- 大括号采用 Attach 风格(与控制语句在同一行)
|
||||
- 指针和引用符号靠左对齐
|
||||
- 自动排序头文件包含
|
||||
- 类访问修饰符缩进为 -4 空格
|
||||
|
||||
### 注意事项
|
||||
|
||||
1. 提交代码前请确保代码已经过格式化
|
||||
2. 不要手动调整已格式化的代码对齐
|
||||
3. 如果某段代码不希望被格式化,可以使用以下注释包围:
|
||||
```cpp
|
||||
// clang-format off
|
||||
// 你的代码
|
||||
// clang-format on
|
||||
```
|
||||
|
||||
### 常见问题
|
||||
|
||||
1. **格式化失败**:
|
||||
- 检查 clang-format 版本是否过低
|
||||
- 确认文件编码为 UTF-8
|
||||
- 验证 .clang-format 文件语法是否正确
|
||||
|
||||
2. **与期望格式不符**:
|
||||
- 检查是否使用了项目根目录下的 .clang-format 配置
|
||||
- 确认没有其他位置的 .clang-format 文件被优先使用
|
||||
|
||||
如有任何问题或建议,欢迎提出 issue 或 pull request。
|
||||
@@ -21,7 +21,7 @@
|
||||
|
||||
### 1. 创建新的开发板目录
|
||||
|
||||
首先在`boards/`目录下创建一个新的目录,例如`my-custom-board/`:
|
||||
首先在`boards/`目录下创建一个新的目录,命名方式应使用 `[品牌名]-[开发板类型]` 的形式,例如 `m5stack-tab5`:
|
||||
|
||||
```bash
|
||||
mkdir main/boards/my-custom-board
|
||||
@@ -87,24 +87,51 @@ mkdir main/boards/my-custom-board
|
||||
|
||||
#### config.json
|
||||
|
||||
在`config.json`中定义编译配置:
|
||||
在`config.json`中定义编译配置,这个文件用于 `scripts/release.py` 脚本自动化编译:
|
||||
|
||||
```json
|
||||
{
|
||||
"target": "esp32s3", // 目标芯片型号: esp32, esp32s3, esp32c3等
|
||||
"target": "esp32s3", // 目标芯片型号: esp32, esp32s3, esp32c3, esp32c6, esp32p4等
|
||||
"builds": [
|
||||
{
|
||||
"name": "my-custom-board", // 开发板名称
|
||||
"name": "my-custom-board", // 开发板名称,用于生成固件包
|
||||
"sdkconfig_append": [
|
||||
// 额外需要的编译配置
|
||||
// 特别 Flash 大小配置
|
||||
"CONFIG_ESPTOOLPY_FLASHSIZE_8MB=y",
|
||||
"CONFIG_PARTITION_TABLE_CUSTOM_FILENAME=\"partitions/v1/8m.csv\""
|
||||
// 特别分区表配置
|
||||
"CONFIG_PARTITION_TABLE_CUSTOM_FILENAME=\"partitions/v2/8m.csv\""
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
**配置项说明:**
|
||||
- `target`: 目标芯片型号,必须与硬件匹配
|
||||
- `name`: 编译输出的固件包名称,建议与目录名一致
|
||||
- `sdkconfig_append`: 额外的 sdkconfig 配置项数组,会追加到默认配置中
|
||||
|
||||
**常用的 sdkconfig_append 配置:**
|
||||
```json
|
||||
// Flash 大小
|
||||
"CONFIG_ESPTOOLPY_FLASHSIZE_4MB=y" // 4MB Flash
|
||||
"CONFIG_ESPTOOLPY_FLASHSIZE_8MB=y" // 8MB Flash
|
||||
"CONFIG_ESPTOOLPY_FLASHSIZE_16MB=y" // 16MB Flash
|
||||
|
||||
// 分区表
|
||||
"CONFIG_PARTITION_TABLE_CUSTOM_FILENAME=\"partitions/v2/4m.csv\"" // 4MB 分区表
|
||||
"CONFIG_PARTITION_TABLE_CUSTOM_FILENAME=\"partitions/v2/8m.csv\"" // 8MB 分区表
|
||||
"CONFIG_PARTITION_TABLE_CUSTOM_FILENAME=\"partitions/v2/16m.csv\"" // 16MB 分区表
|
||||
|
||||
// 语言配置
|
||||
"CONFIG_LANGUAGE_EN_US=y" // 英语
|
||||
"CONFIG_LANGUAGE_ZH_CN=y" // 简体中文
|
||||
|
||||
// 唤醒词配置
|
||||
"CONFIG_USE_DEVICE_AEC=y" // 启用设备端 AEC
|
||||
"CONFIG_WAKE_WORD_DISABLED=y" // 禁用唤醒词
|
||||
```
|
||||
|
||||
### 3. 编写板级初始化代码
|
||||
|
||||
创建一个`my_custom_board.cc`文件,实现开发板的所有初始化逻辑。
|
||||
@@ -131,10 +158,6 @@ mkdir main/boards/my-custom-board
|
||||
|
||||
#define TAG "MyCustomBoard"
|
||||
|
||||
// 声明字体
|
||||
LV_FONT_DECLARE(font_puhui_16_4);
|
||||
LV_FONT_DECLARE(font_awesome_16_4);
|
||||
|
||||
class MyCustomBoard : public WifiBoard {
|
||||
private:
|
||||
i2c_master_bus_handle_t codec_i2c_bus_;
|
||||
@@ -174,8 +197,9 @@ private:
|
||||
void InitializeButtons() {
|
||||
boot_button_.OnClick([this]() {
|
||||
auto& app = Application::GetInstance();
|
||||
if (app.GetDeviceState() == kDeviceStateStarting && !WifiStation::GetInstance().IsConnected()) {
|
||||
ResetWifiConfiguration();
|
||||
if (app.GetDeviceState() == kDeviceStateStarting) {
|
||||
EnterWifiConfigMode();
|
||||
return;
|
||||
}
|
||||
app.ToggleChatState();
|
||||
});
|
||||
@@ -212,12 +236,7 @@ private:
|
||||
display_ = new SpiLcdDisplay(panel_io, panel,
|
||||
DISPLAY_WIDTH, DISPLAY_HEIGHT,
|
||||
DISPLAY_OFFSET_X, DISPLAY_OFFSET_Y,
|
||||
DISPLAY_MIRROR_X, DISPLAY_MIRROR_Y, DISPLAY_SWAP_XY,
|
||||
{
|
||||
.text_font = &font_puhui_16_4,
|
||||
.icon_font = &font_awesome_16_4,
|
||||
.emoji_font = font_emoji_32_init(),
|
||||
});
|
||||
DISPLAY_MIRROR_X, DISPLAY_MIRROR_Y, DISPLAY_SWAP_XY);
|
||||
}
|
||||
|
||||
// MCP Tools 初始化
|
||||
@@ -269,7 +288,106 @@ public:
|
||||
DECLARE_BOARD(MyCustomBoard);
|
||||
```
|
||||
|
||||
### 4. 创建README.md
|
||||
### 4. 添加构建系统配置
|
||||
|
||||
#### 在 Kconfig.projbuild 中添加开发板选项
|
||||
|
||||
打开 `main/Kconfig.projbuild` 文件,在 `choice BOARD_TYPE` 部分添加新的开发板配置项:
|
||||
|
||||
```kconfig
|
||||
choice BOARD_TYPE
|
||||
prompt "Board Type"
|
||||
default BOARD_TYPE_BREAD_COMPACT_WIFI
|
||||
help
|
||||
Board type. 开发板类型
|
||||
|
||||
# ... 其他开发板选项 ...
|
||||
|
||||
config BOARD_TYPE_MY_CUSTOM_BOARD
|
||||
bool "My Custom Board (我的自定义开发板)"
|
||||
depends on IDF_TARGET_ESP32S3 # 根据你的目标芯片修改
|
||||
endchoice
|
||||
```
|
||||
|
||||
**注意事项:**
|
||||
- `BOARD_TYPE_MY_CUSTOM_BOARD` 是配置项名称,需要全大写,使用下划线分隔
|
||||
- `depends on` 指定了目标芯片类型(如 `IDF_TARGET_ESP32S3`、`IDF_TARGET_ESP32C3` 等)
|
||||
- 描述文字可以使用中英文
|
||||
|
||||
#### 在 CMakeLists.txt 中添加开发板配置
|
||||
|
||||
打开 `main/CMakeLists.txt` 文件,在开发板类型判断部分添加新的配置:
|
||||
|
||||
```cmake
|
||||
# 在 elseif 链中添加你的开发板配置
|
||||
elseif(CONFIG_BOARD_TYPE_MY_CUSTOM_BOARD)
|
||||
set(BOARD_TYPE "my-custom-board") # 与目录名一致
|
||||
set(BUILTIN_TEXT_FONT font_puhui_basic_20_4) # 根据屏幕大小选择合适的字体
|
||||
set(BUILTIN_ICON_FONT font_awesome_20_4)
|
||||
set(DEFAULT_EMOJI_COLLECTION twemoji_64) # 可选,如果需要表情显示
|
||||
endif()
|
||||
```
|
||||
|
||||
**字体和表情配置说明:**
|
||||
|
||||
根据屏幕分辨率选择合适的字体大小:
|
||||
- 小屏幕(128x64 OLED):`font_puhui_basic_14_1` / `font_awesome_14_1`
|
||||
- 中小屏幕(240x240):`font_puhui_basic_16_4` / `font_awesome_16_4`
|
||||
- 中等屏幕(240x320):`font_puhui_basic_20_4` / `font_awesome_20_4`
|
||||
- 大屏幕(480x320+):`font_puhui_basic_30_4` / `font_awesome_30_4`
|
||||
|
||||
表情集合选项:
|
||||
- `twemoji_32` - 32x32 像素表情(小屏幕)
|
||||
- `twemoji_64` - 64x64 像素表情(大屏幕)
|
||||
|
||||
### 5. 配置和编译
|
||||
|
||||
#### 方法一:使用 idf.py 手动配置
|
||||
|
||||
1. **设置目标芯片**(首次配置或更换芯片时):
|
||||
```bash
|
||||
# 对于 ESP32-S3
|
||||
idf.py set-target esp32s3
|
||||
|
||||
# 对于 ESP32-C3
|
||||
idf.py set-target esp32c3
|
||||
|
||||
# 对于 ESP32
|
||||
idf.py set-target esp32
|
||||
```
|
||||
|
||||
2. **清理旧配置**:
|
||||
```bash
|
||||
idf.py fullclean
|
||||
```
|
||||
|
||||
3. **进入配置菜单**:
|
||||
```bash
|
||||
idf.py menuconfig
|
||||
```
|
||||
|
||||
在菜单中导航到:`Xiaozhi Assistant` -> `Board Type`,选择你的自定义开发板。
|
||||
|
||||
4. **编译和烧录**:
|
||||
```bash
|
||||
idf.py build
|
||||
idf.py flash monitor
|
||||
```
|
||||
|
||||
#### 方法二:使用 release.py 脚本(推荐)
|
||||
|
||||
如果你的开发板目录下有 `config.json` 文件,可以使用此脚本自动完成配置和编译:
|
||||
|
||||
```bash
|
||||
python scripts/release.py my-custom-board
|
||||
```
|
||||
|
||||
此脚本会自动:
|
||||
- 读取 `config.json` 中的 `target` 配置并设置目标芯片
|
||||
- 应用 `sdkconfig_append` 中的编译选项
|
||||
- 完成编译并打包固件
|
||||
|
||||
### 6. 创建README.md
|
||||
|
||||
在README.md中说明开发板的特性、硬件要求、编译和烧录步骤:
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -6,6 +6,32 @@ config OTA_URL
|
||||
help
|
||||
The application will access this URL to check for new firmwares and server address.
|
||||
|
||||
choice
|
||||
prompt "Flash Assets"
|
||||
default FLASH_DEFAULT_ASSETS if !USE_EMOTE_MESSAGE_STYLE
|
||||
default FLASH_EXPRESSION_ASSETS if USE_EMOTE_MESSAGE_STYLE
|
||||
help
|
||||
Select the assets to flash.
|
||||
|
||||
config FLASH_NONE_ASSETS
|
||||
bool "Do not flash assets"
|
||||
config FLASH_DEFAULT_ASSETS
|
||||
bool "Flash Default Assets"
|
||||
depends on !USE_EMOTE_MESSAGE_STYLE
|
||||
config FLASH_CUSTOM_ASSETS
|
||||
bool "Flash Custom Assets"
|
||||
config FLASH_EXPRESSION_ASSETS
|
||||
bool "Flash Emote Assets"
|
||||
depends on USE_EMOTE_MESSAGE_STYLE
|
||||
endchoice
|
||||
|
||||
config CUSTOM_ASSETS_FILE
|
||||
depends on FLASH_CUSTOM_ASSETS
|
||||
string "Custom Assets File"
|
||||
default "assets.bin"
|
||||
help
|
||||
The custom assets file to flash.
|
||||
It can be a local file relative to the project directory or a remote url.
|
||||
|
||||
choice
|
||||
prompt "Default Language"
|
||||
@@ -57,6 +83,38 @@ choice
|
||||
bool "Ukrainian"
|
||||
config LANGUAGE_RO_RO
|
||||
bool "Romanian"
|
||||
config LANGUAGE_BG_BG
|
||||
bool "Bulgarian"
|
||||
config LANGUAGE_CA_ES
|
||||
bool "Catalan"
|
||||
config LANGUAGE_DA_DK
|
||||
bool "Danish"
|
||||
config LANGUAGE_EL_GR
|
||||
bool "Greek"
|
||||
config LANGUAGE_FA_IR
|
||||
bool "Persian"
|
||||
config LANGUAGE_FIL_PH
|
||||
bool "Filipino"
|
||||
config LANGUAGE_HE_IL
|
||||
bool "Hebrew"
|
||||
config LANGUAGE_HR_HR
|
||||
bool "Croatian"
|
||||
config LANGUAGE_HU_HU
|
||||
bool "Hungarian"
|
||||
config LANGUAGE_MS_MY
|
||||
bool "Malay"
|
||||
config LANGUAGE_NB_NO
|
||||
bool "Norwegian"
|
||||
config LANGUAGE_NL_NL
|
||||
bool "Dutch"
|
||||
config LANGUAGE_SK_SK
|
||||
bool "Slovak"
|
||||
config LANGUAGE_SL_SI
|
||||
bool "Slovenian"
|
||||
config LANGUAGE_SV_SE
|
||||
bool "Swedish"
|
||||
config LANGUAGE_SR_RS
|
||||
bool "Serbian"
|
||||
endchoice
|
||||
|
||||
choice BOARD_TYPE
|
||||
@@ -65,58 +123,70 @@ choice BOARD_TYPE
|
||||
help
|
||||
Board type. 开发板类型
|
||||
config BOARD_TYPE_BREAD_COMPACT_WIFI
|
||||
bool "面包板新版接线(WiFi)"
|
||||
bool "Bread Compact WiFi (面包板)"
|
||||
depends on IDF_TARGET_ESP32S3
|
||||
config BOARD_TYPE_BREAD_COMPACT_WIFI_LCD
|
||||
bool "面包板新版接线(WiFi)+ LCD"
|
||||
bool "Bread Compact WiFi + LCD (面包板)"
|
||||
depends on IDF_TARGET_ESP32S3
|
||||
config BOARD_TYPE_BREAD_COMPACT_WIFI_CAM
|
||||
bool "面包板新版接线(WiFi)+ LCD + Camera"
|
||||
bool "Bread Compact WiFi + LCD + Camera (面包板)"
|
||||
depends on IDF_TARGET_ESP32S3
|
||||
config BOARD_TYPE_BREAD_COMPACT_ML307
|
||||
bool "面包板新版接线(ML307 AT)"
|
||||
bool "Bread Compact ML307/EC801E (面包板 4G)"
|
||||
depends on IDF_TARGET_ESP32S3
|
||||
config BOARD_TYPE_BREAD_COMPACT_NT26
|
||||
bool "Bread Compact NT26 (面包板 4G)"
|
||||
depends on IDF_TARGET_ESP32S3
|
||||
config BOARD_TYPE_BREAD_COMPACT_ESP32
|
||||
bool "面包板(WiFi) ESP32 DevKit"
|
||||
bool "Bread Compact ESP32 DevKit (面包板)"
|
||||
depends on IDF_TARGET_ESP32
|
||||
config BOARD_TYPE_BREAD_COMPACT_ESP32_LCD
|
||||
bool "面包板(WiFi+ LCD) ESP32 DevKit"
|
||||
bool "Bread Compact ESP32 DevKit + LCD (面包板)"
|
||||
depends on IDF_TARGET_ESP32
|
||||
config BOARD_TYPE_XMINI_C3_V3
|
||||
bool "虾哥 Mini C3 V3"
|
||||
bool "Xmini C3 V3"
|
||||
depends on IDF_TARGET_ESP32C3
|
||||
config BOARD_TYPE_XMINI_C3_4G
|
||||
bool "虾哥 Mini C3 4G"
|
||||
bool "Xmini C3 4G"
|
||||
depends on IDF_TARGET_ESP32C3
|
||||
config BOARD_TYPE_XMINI_C3
|
||||
bool "虾哥 Mini C3"
|
||||
bool "Xmini C3"
|
||||
depends on IDF_TARGET_ESP32C3
|
||||
config BOARD_TYPE_ESP32S3_KORVO2_V3
|
||||
bool "ESP32S3_KORVO2_V3开发板"
|
||||
config BOARD_TYPE_ESP_KORVO2_V3
|
||||
bool "Espressif Korvo2 V3"
|
||||
depends on IDF_TARGET_ESP32S3
|
||||
config BOARD_TYPE_ESP_KORVO2_V3_RNDIS
|
||||
bool "Espressif Korvo2 V3 RNDIS"
|
||||
depends on IDF_TARGET_ESP32S3
|
||||
config BOARD_TYPE_ESP_SPARKBOT
|
||||
bool "ESP-SparkBot开发板"
|
||||
bool "Espressif SparkBot"
|
||||
depends on IDF_TARGET_ESP32S3
|
||||
config BOARD_TYPE_ESP_SENSAIRSHUTTLE
|
||||
bool "Espressif ESP-SensairShuttle"
|
||||
depends on IDF_TARGET_ESP32C5
|
||||
config BOARD_TYPE_ESP_SPOT_S3
|
||||
bool "ESP-Spot-S3"
|
||||
bool "Espressif Spot-S3"
|
||||
depends on IDF_TARGET_ESP32S3
|
||||
config BOARD_TYPE_ESP_SPOT_C5
|
||||
bool "Espressif Spot-C5"
|
||||
depends on IDF_TARGET_ESP32C5
|
||||
config BOARD_TYPE_ESP_HI
|
||||
bool "ESP-HI"
|
||||
bool "Espressif 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"
|
||||
bool "Espressif ESP-BOX-3"
|
||||
depends on IDF_TARGET_ESP32S3
|
||||
config BOARD_TYPE_ESP_BOX
|
||||
bool "ESP BOX"
|
||||
bool "Espressif ESP-BOX"
|
||||
depends on IDF_TARGET_ESP32S3
|
||||
config BOARD_TYPE_ESP_BOX_LITE
|
||||
bool "ESP BOX Lite"
|
||||
bool "Espressif ESP-BOX-Lite"
|
||||
depends on IDF_TARGET_ESP32S3
|
||||
config BOARD_TYPE_KEVIN_BOX_1
|
||||
bool "Kevin Box 1"
|
||||
config BOARD_TYPE_ESP_P4_FUNCTION_EV_BOARD
|
||||
bool "Espressif ESP-P4-Function-EV-Board"
|
||||
depends on IDF_TARGET_ESP32P4
|
||||
config BOARD_TYPE_ECHOEAR
|
||||
bool "EchoEar"
|
||||
depends on IDF_TARGET_ESP32S3
|
||||
config BOARD_TYPE_KEVIN_BOX_2
|
||||
bool "Kevin Box 2"
|
||||
@@ -125,25 +195,25 @@ choice BOARD_TYPE
|
||||
bool "Kevin C3"
|
||||
depends on IDF_TARGET_ESP32C3
|
||||
config BOARD_TYPE_KEVIN_SP_V3_DEV
|
||||
bool "Kevin SP V3开发板"
|
||||
bool "Kevin SP V3"
|
||||
depends on IDF_TARGET_ESP32S3
|
||||
config BOARD_TYPE_KEVIN_SP_V4_DEV
|
||||
bool "Kevin SP V4开发板"
|
||||
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开发板"
|
||||
bool "鱼鹰科技 3.13LCD"
|
||||
depends on IDF_TARGET_ESP32S3
|
||||
config BOARD_TYPE_LICHUANG_DEV
|
||||
bool "立创·实战派ESP32-S3开发板"
|
||||
config BOARD_TYPE_CGC
|
||||
bool "CGC"
|
||||
depends on IDF_TARGET_ESP32
|
||||
config BOARD_TYPE_CGC_144
|
||||
bool "CGC 144"
|
||||
depends on IDF_TARGET_ESP32
|
||||
config BOARD_TYPE_LICHUANG_DEV_S3
|
||||
bool "立创·实战派 ESP32-S3"
|
||||
depends on IDF_TARGET_ESP32S3
|
||||
config BOARD_TYPE_LICHUANG_C3_DEV
|
||||
bool "立创·实战派ESP32-C3开发板"
|
||||
config BOARD_TYPE_LICHUANG_DEV_C3
|
||||
bool "立创·实战派 ESP32-C3"
|
||||
depends on IDF_TARGET_ESP32C3
|
||||
config BOARD_TYPE_DF_K10
|
||||
bool "DFRobot 行空板 k10"
|
||||
@@ -151,10 +221,10 @@ choice BOARD_TYPE
|
||||
config BOARD_TYPE_DF_S3_AI_CAM
|
||||
bool "DFRobot ESP32-S3 AI智能摄像头模块"
|
||||
depends on IDF_TARGET_ESP32S3
|
||||
config BOARD_TYPE_MAGICLICK_2P4
|
||||
config BOARD_TYPE_MAGICLICK_S3_2P4
|
||||
bool "神奇按钮 Magiclick_2.4"
|
||||
depends on IDF_TARGET_ESP32S3
|
||||
config BOARD_TYPE_MAGICLICK_2P5
|
||||
config BOARD_TYPE_MAGICLICK_S3_2P5
|
||||
bool "神奇按钮 Magiclick_2.5"
|
||||
depends on IDF_TARGET_ESP32S3
|
||||
config BOARD_TYPE_MAGICLICK_C3
|
||||
@@ -169,61 +239,113 @@ choice BOARD_TYPE
|
||||
config BOARD_TYPE_M5STACK_CORE_TAB5
|
||||
bool "M5Stack Tab5"
|
||||
depends on IDF_TARGET_ESP32P4
|
||||
config BOARD_TYPE_ATOMS3_ECHO_BASE
|
||||
bool "AtomS3 + Echo Base"
|
||||
config BOARD_TYPE_M5STACK_ATOM_S3_ECHO_BASE
|
||||
bool "M5Stack AtomS3 + Echo Base"
|
||||
depends on IDF_TARGET_ESP32S3
|
||||
config BOARD_TYPE_ATOMS3R_ECHO_BASE
|
||||
bool "AtomS3R + Echo Base"
|
||||
config BOARD_TYPE_M5STACK_ATOM_S3R_ECHO_BASE
|
||||
bool "M5Stack AtomS3R + Echo Base"
|
||||
depends on IDF_TARGET_ESP32S3
|
||||
config BOARD_TYPE_ATOMS3R_CAM_M12_ECHO_BASE
|
||||
bool "AtomS3R CAM/M12 + Echo Base"
|
||||
config BOARD_TYPE_M5STACK_ATOM_S3R_CAM_M12_ECHO_BASE
|
||||
bool "M5Stack AtomS3R CAM/M12 + Echo Base"
|
||||
depends on IDF_TARGET_ESP32S3
|
||||
config BOARD_TYPE_ATOM_ECHOS3R
|
||||
bool "AtomEchoS3R"
|
||||
config BOARD_TYPE_M5STACK_ATOM_ECHOS3R
|
||||
bool "M5Stack AtomEchoS3R"
|
||||
depends on IDF_TARGET_ESP32S3
|
||||
config BOARD_TYPE_ATOMMATRIX_ECHO_BASE
|
||||
bool "AtomMatrix + Echo Base"
|
||||
config BOARD_TYPE_M5STACK_CARDPUTER_ADV
|
||||
bool "M5Stack Cardputer Adv"
|
||||
depends on IDF_TARGET_ESP32S3
|
||||
config BOARD_TYPE_M5STACK_ATOM_MATRIX_ECHO_BASE
|
||||
bool "M5Stack AtomMatrix + Echo Base"
|
||||
depends on IDF_TARGET_ESP32
|
||||
config BOARD_TYPE_ESP32S3_AUDIO_BOARD
|
||||
config BOARD_TYPE_WAVESHARE_ESP32_S3_AUDIO_BOARD
|
||||
bool "Waveshare ESP32-S3-Audio-Board"
|
||||
depends on IDF_TARGET_ESP32S3
|
||||
config BOARD_TYPE_ESP32S3_Touch_AMOLED_1_8
|
||||
config BOARD_TYPE_WAVESHARE_ESP32_S3_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
|
||||
config BOARD_TYPE_WAVESHARE_ESP32_S3_TOUCH_AMOLED_2_06
|
||||
bool "Waveshare ESP32-S3-Touch-AMOLED-2.06"
|
||||
config BOARD_TYPE_ESP32S3_Touch_AMOLED_1_75
|
||||
depends on IDF_TARGET_ESP32S3
|
||||
config BOARD_TYPE_WAVESHARE_ESP32_C6_TOUCH_AMOLED_2_06
|
||||
bool "Waveshare ESP32-C6-Touch-AMOLED-2.06"
|
||||
depends on IDF_TARGET_ESP32C6
|
||||
config BOARD_TYPE_WAVESHARE_ESP32_S3_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
|
||||
config BOARD_TYPE_WAVESHARE_ESP32_S3_TOUCH_LCD_1_83
|
||||
bool "Waveshare ESP32-S3-Touch-LCD-1.83"
|
||||
depends on IDF_TARGET_ESP32S3
|
||||
config BOARD_TYPE_WAVESHARE_ESP32_S3_TOUCH_LCD_4B
|
||||
bool "Waveshare ESP32-S3-Touch-LCD-4B"
|
||||
depends on IDF_TARGET_ESP32S3
|
||||
config BOARD_TYPE_WAVESHARE_ESP32_S3_TOUCH_LCD_4_3C
|
||||
bool "Waveshare ESP32-S3-Touch-LCD-4.3C"
|
||||
depends on IDF_TARGET_ESP32S3
|
||||
config BOARD_TYPE_WAVESHARE_ESP32_S3_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
|
||||
config BOARD_TYPE_WAVESHARE_ESP32_S3_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
|
||||
config BOARD_TYPE_WAVESHARE_ESP32_S3_TOUCH_LCD_1_46
|
||||
bool "Waveshare ESP32-S3-Touch-LCD-1.46"
|
||||
depends on IDF_TARGET_ESP32S3
|
||||
config BOARD_TYPE_ESP32C6_LCD_1_69
|
||||
config BOARD_TYPE_WAVESHARE_ESP32_C6_LCD_1_69
|
||||
bool "Waveshare ESP32-C6-LCD-1.69"
|
||||
depends on IDF_TARGET_ESP32C6
|
||||
config BOARD_TYPE_ESP32C6_Touch_AMOLED_1_43
|
||||
config BOARD_TYPE_WAVESHARE_ESP32_C6_TOUCH_LCD_1_83
|
||||
bool "Waveshare ESP32-C6-Touch-LCD-1.83"
|
||||
depends on IDF_TARGET_ESP32C6
|
||||
config BOARD_TYPE_WAVESHARE_ESP32_C6_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
|
||||
config BOARD_TYPE_WAVESHARE_ESP32_C6_TOUCH_AMOLED_1_32
|
||||
bool "Waveshare ESP32-C6-Touch-AMOLOED-1.32"
|
||||
depends on IDF_TARGET_ESP32C6
|
||||
config BOARD_TYPE_WAVESHARE_ESP32_C6_TOUCH_AMOLED_1_8
|
||||
bool "Waveshare ESP32-C6-Touch-AMOLED-1.8"
|
||||
depends on IDF_TARGET_ESP32C6
|
||||
config BOARD_TYPE_WAVESHARE_ESP32_S3_TOUCH_AMOLED_1_32
|
||||
bool "Waveshare ESP32-S3-Touch-AMOLOED-1.32"
|
||||
depends on IDF_TARGET_ESP32S3
|
||||
config BOARD_TYPE_WAVESHARE_ESP32_S3_TOUCH_LCD_3_49
|
||||
bool "Waveshare ESP32-S3-Touch-LCD-3.49"
|
||||
depends on IDF_TARGET_ESP32S3
|
||||
config BOARD_TYPE_WAVESHARE_ESP32_S3_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
|
||||
config BOARD_TYPE_WAVESHARE_ESP32_S3_ePaper_1_54
|
||||
bool "Waveshare ESP32-S3-ePaper-1.54"
|
||||
depends on IDF_TARGET_ESP32S3
|
||||
config BOARD_TYPE_WAVESHARE_ESP32_S3_RLCD_4_2
|
||||
bool "Waveshare ESP32-S3-RLCD-4.2"
|
||||
depends on IDF_TARGET_ESP32S3
|
||||
config BOARD_TYPE_WAVESHARE_ESP32_S3_TOUCH_LCD_3_5B
|
||||
bool "Waveshare ESP32-S3-Touch-LCD-3.5B"
|
||||
depends on IDF_TARGET_ESP32S3
|
||||
config BOARD_TYPE_ESP32P4_NANO
|
||||
config BOARD_TYPE_WAVESHARE_ESP32_P4_NANO
|
||||
bool "Waveshare ESP32-P4-NANO"
|
||||
depends on IDF_TARGET_ESP32P4
|
||||
config BOARD_TYPE_ESP32P4_WIFI6_Touch_LCD_4B
|
||||
config BOARD_TYPE_WAVESHARE_ESP32_P4_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"
|
||||
config BOARD_TYPE_WAVESHARE_ESP32_P4_WIFI6_TOUCH_LCD_7B
|
||||
bool "Waveshare ESP32-P4-WIFI6-Touch-LCD-7B"
|
||||
depends on IDF_TARGET_ESP32P4
|
||||
config BOARD_TYPE_WAVESHARE_ESP32_P4_WIFI6_TOUCH_LCD_3_4C
|
||||
bool "Waveshare ESP32-P4-WIFI6-Touch-LCD-3.4C"
|
||||
depends on IDF_TARGET_ESP32P4
|
||||
config BOARD_TYPE_WAVESHARE_ESP32_P4_WIFI6_TOUCH_LCD_4C
|
||||
bool "Waveshare ESP32-P4-WIFI6-Touch-LCD-4C"
|
||||
depends on IDF_TARGET_ESP32P4
|
||||
config BOARD_TYPE_WAVESHARE_ESP32_P4_WIFI6_TOUCH_LCD_7
|
||||
bool "Waveshare ESP32-P4-WIFI6-Touch-LCD-7"
|
||||
depends on IDF_TARGET_ESP32P4
|
||||
config BOARD_TYPE_WAVESHARE_ESP32_P4_WIFI6_TOUCH_LCD_8
|
||||
bool "Waveshare ESP32-P4-WIFI6-Touch-LCD-8"
|
||||
depends on IDF_TARGET_ESP32P4
|
||||
config BOARD_TYPE_WAVESHARE_ESP32_P4_WIFI6_TOUCH_LCD_10_1
|
||||
bool "Waveshare ESP32-P4-WIFI6-Touch-LCD-10.1"
|
||||
depends on IDF_TARGET_ESP32P4
|
||||
config BOARD_TYPE_TUDOUZI
|
||||
bool "土豆子"
|
||||
@@ -243,9 +365,15 @@ choice BOARD_TYPE
|
||||
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_LILYGO_T_DISPLAY_P4
|
||||
bool "LILYGO T-Display-P4"
|
||||
depends on IDF_TARGET_ESP32P4
|
||||
config BOARD_TYPE_MOVECALL_MOJI_ESP32S3
|
||||
bool "Movecall Moji 小智AI衍生版"
|
||||
depends on IDF_TARGET_ESP32S3
|
||||
config BOARD_TYPE_MOVECALL_MOJI2_ESP32C5
|
||||
bool "Movecall Moji2.0 小智AI衍生版"
|
||||
depends on IDF_TARGET_ESP32C5
|
||||
config BOARD_TYPE_MOVECALL_CUICAN_ESP32S3
|
||||
bool "Movecall CuiCan 璀璨·AI吊坠"
|
||||
depends on IDF_TARGET_ESP32S3
|
||||
@@ -262,7 +390,7 @@ choice BOARD_TYPE
|
||||
bool "正点原子DNESP32S3-BOX2-WIFI"
|
||||
depends on IDF_TARGET_ESP32S3
|
||||
config BOARD_TYPE_ATK_DNESP32S3_BOX2_4G
|
||||
bool "正点原子DNESP32S3-BOX2-4G"
|
||||
bool "正点原子DNESP32S3-BOX2-4G"
|
||||
depends on IDF_TARGET_ESP32S3
|
||||
config BOARD_TYPE_ATK_DNESP32S3M_WIFI
|
||||
bool "正点原子DNESP32S3M-WIFI"
|
||||
@@ -273,29 +401,32 @@ choice BOARD_TYPE
|
||||
config BOARD_TYPE_DU_CHATX
|
||||
bool "嘟嘟开发板CHATX(wifi)"
|
||||
depends on IDF_TARGET_ESP32S3
|
||||
config BOARD_TYPE_ESP32S3_Taiji_Pi
|
||||
config BOARD_TYPE_TAIJI_PI_S3
|
||||
bool "太极小派esp32s3"
|
||||
depends on IDF_TARGET_ESP32S3
|
||||
config BOARD_TYPE_XINGZHI_Cube_0_85TFT_WIFI
|
||||
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
|
||||
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
|
||||
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
|
||||
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
|
||||
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
|
||||
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"
|
||||
config BOARD_TYPE_XINGZHI_METAL_1_54_WIFI
|
||||
bool "无名科技星智1.54 METAL(wifi)"
|
||||
depends on IDF_TARGET_ESP32S3
|
||||
config BOARD_TYPE_SEEED_STUDIO_SENSECAP_WATCHER
|
||||
bool "Seeed Studio SenseCAP Watcher"
|
||||
depends on IDF_TARGET_ESP32S3
|
||||
config BOARD_TYPE_DOIT_S3_AIBOX
|
||||
bool "四博智联AI陪伴盒子"
|
||||
@@ -318,45 +449,77 @@ choice BOARD_TYPE
|
||||
config BOARD_TYPE_ZHENGCHEN_1_54TFT_ML307
|
||||
bool "征辰科技1.54(ML307)"
|
||||
depends on IDF_TARGET_ESP32S3
|
||||
config BOARD_TYPE_ZHENGCHEN_CAM
|
||||
bool "征辰科技AI Camera"
|
||||
depends on IDF_TARGET_ESP32S3
|
||||
config BOARD_TYPE_ZHENGCHEN_CAM_ML307
|
||||
bool "征辰科技AI Camera(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
|
||||
config BOARD_TYPE_SPOTPEAR_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
|
||||
config BOARD_TYPE_SPOTPEAR_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 "九川智能"
|
||||
depends on IDF_TARGET_ESP32S3
|
||||
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"
|
||||
bool "Surfer-C3-1.14TFT"
|
||||
depends on IDF_TARGET_ESP32C3
|
||||
config BOARD_TYPE_YUNLIAO_S3
|
||||
bool "小智云聊-S3"
|
||||
depends on IDF_TARGET_ESP32S3
|
||||
config BOARD_TYPE_WIRELESS_TAG_WTP4C5MP07S
|
||||
bool "Wireless-Tag WTP4C5MP07S"
|
||||
depends on IDF_TARGET_ESP32P4
|
||||
config BOARD_TYPE_AIPI_LITE
|
||||
bool "AIPI-Lite"
|
||||
depends on IDF_TARGET_ESP32S3
|
||||
config BOARD_TYPE_HU_087
|
||||
bool "HU-087"
|
||||
depends on IDF_TARGET_ESP32S3
|
||||
endchoice
|
||||
|
||||
choice
|
||||
depends on BOARD_TYPE_LILYGO_T_DISPLAY_P4
|
||||
prompt "Select the screen type"
|
||||
default SCREEN_TYPE_HI8561
|
||||
config SCREEN_TYPE_HI8561
|
||||
bool "HI8561"
|
||||
config SCREEN_TYPE_RM69A10
|
||||
bool "RM69A10"
|
||||
endchoice
|
||||
|
||||
choice
|
||||
depends on BOARD_TYPE_LILYGO_T_DISPLAY_P4
|
||||
prompt "Select the color format of the screen"
|
||||
default SCREEN_PIXEL_FORMAT_RGB565
|
||||
config SCREEN_PIXEL_FORMAT_RGB565
|
||||
bool "RGB565"
|
||||
config SCREEN_PIXEL_FORMAT_RGB888
|
||||
bool "RGB888"
|
||||
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
|
||||
@@ -364,131 +527,147 @@ choice ESP_S3_LCD_EV_Board_Version_TYPE
|
||||
endchoice
|
||||
|
||||
choice DISPLAY_OLED_TYPE
|
||||
depends on BOARD_TYPE_BREAD_COMPACT_WIFI || BOARD_TYPE_BREAD_COMPACT_ML307 || BOARD_TYPE_BREAD_COMPACT_ESP32
|
||||
depends on BOARD_TYPE_BREAD_COMPACT_WIFI || BOARD_TYPE_BREAD_COMPACT_ML307 || BOARD_TYPE_BREAD_COMPACT_NT26 || BOARD_TYPE_BREAD_COMPACT_ESP32 || BOARD_TYPE_HU_087
|
||||
prompt "OLED Type"
|
||||
default OLED_SSD1306_128X32
|
||||
help
|
||||
OLED 屏幕类型选择
|
||||
OLED Monochrome Display Type
|
||||
config OLED_SSD1306_128X32
|
||||
bool "SSD1306, 分辨率128*32"
|
||||
bool "SSD1306 128*32"
|
||||
config OLED_SSD1306_128X64
|
||||
bool "SSD1306, 分辨率128*64"
|
||||
bool "SSD1306 128*64"
|
||||
config OLED_SH1106_128X64
|
||||
bool "SH1106, 分辨率128*64"
|
||||
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
|
||||
depends on BOARD_TYPE_BREAD_COMPACT_WIFI_LCD || BOARD_TYPE_BREAD_COMPACT_ESP32_LCD || BOARD_TYPE_CGC || BOARD_TYPE_BREAD_COMPACT_WIFI_CAM
|
||||
prompt "LCD Type"
|
||||
default LCD_ST7789_240X320
|
||||
help
|
||||
屏幕类型选择
|
||||
LCD Display Type
|
||||
config LCD_ST7789_240X320
|
||||
bool "ST7789, 分辨率240*320, IPS"
|
||||
bool "ST7789 240*320, IPS"
|
||||
config LCD_ST7789_240X320_NO_IPS
|
||||
bool "ST7789, 分辨率240*320, 非IPS"
|
||||
bool "ST7789 240*320, Non-IPS"
|
||||
config LCD_ST7789_170X320
|
||||
bool "ST7789, 分辨率170*320"
|
||||
bool "ST7789 170*320"
|
||||
config LCD_ST7789_172X320
|
||||
bool "ST7789, 分辨率172*320"
|
||||
bool "ST7789 172*320"
|
||||
config LCD_ST7789_240X280
|
||||
bool "ST7789, 分辨率240*280"
|
||||
bool "ST7789 240*280"
|
||||
config LCD_ST7789_240X240
|
||||
bool "ST7789, 分辨率240*240"
|
||||
bool "ST7789 240*240"
|
||||
config LCD_ST7789_240X240_7PIN
|
||||
bool "ST7789, 分辨率240*240, 7PIN"
|
||||
bool "ST7789 240*240, 7PIN"
|
||||
config LCD_ST7789_240X135
|
||||
bool "ST7789, 分辨率240*135"
|
||||
bool "ST7789 240*135"
|
||||
config LCD_ST7735_128X160
|
||||
bool "ST7735, 分辨率128*160"
|
||||
bool "ST7735 128*160"
|
||||
config LCD_ST7735_128X128
|
||||
bool "ST7735, 分辨率128*128"
|
||||
bool "ST7735 128*128"
|
||||
config LCD_ST7796_320X480
|
||||
bool "ST7796, 分辨率320*480 IPS"
|
||||
bool "ST7796 320*480 IPS"
|
||||
config LCD_ST7796_320X480_NO_IPS
|
||||
bool "ST7796, 分辨率320*480, 非IPS"
|
||||
bool "ST7796 320*480, Non-IPS"
|
||||
config LCD_ILI9341_240X320
|
||||
bool "ILI9341, 分辨率240*320"
|
||||
bool "ILI9341 240*320"
|
||||
config LCD_ILI9341_240X320_NO_IPS
|
||||
bool "ILI9341, 分辨率240*320, 非IPS"
|
||||
bool "ILI9341 240*320, Non-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"
|
||||
bool "GC9A01 240*240 Circle"
|
||||
config LCD_CUSTOM
|
||||
bool "自定义屏幕参数"
|
||||
bool "Custom LCD (自定义屏幕参数)"
|
||||
endchoice
|
||||
|
||||
choice DISPLAY_ESP32S3_KORVO2_V3
|
||||
depends on BOARD_TYPE_ESP32S3_KORVO2_V3
|
||||
depends on BOARD_TYPE_ESP_KORVO2_V3 || BOARD_TYPE_ESP_KORVO2_V3_RNDIS
|
||||
prompt "ESP32S3_KORVO2_V3 LCD Type"
|
||||
default LCD_ST7789
|
||||
default ESP32S3_KORVO2_V3_LCD_ST7789
|
||||
help
|
||||
屏幕类型选择
|
||||
config LCD_ST7789
|
||||
bool "ST7789, 分辨率240*280"
|
||||
config LCD_ILI9341
|
||||
bool "ILI9341, 分辨率240*320"
|
||||
LCD Display Type
|
||||
config ESP32S3_KORVO2_V3_LCD_ST7789
|
||||
bool "ST7789 240*280"
|
||||
config ESP32S3_KORVO2_V3_LCD_ILI9341
|
||||
bool "ILI9341 240*320"
|
||||
endchoice
|
||||
|
||||
choice DISPLAY_ESP32S3_AUDIO_BOARD
|
||||
depends on BOARD_TYPE_ESP32S3_AUDIO_BOARD
|
||||
depends on BOARD_TYPE_WAVESHARE_ESP32_S3_AUDIO_BOARD
|
||||
prompt "ESP32S3_AUDIO_BOARD LCD Type"
|
||||
default LCD_JD9853
|
||||
default AUDIO_BOARD_LCD_JD9853
|
||||
help
|
||||
屏幕类型选择
|
||||
config LCD_JD9853
|
||||
bool "JD9853, 分辨率320*172"
|
||||
config LCD_ST7789
|
||||
bool "ST7789, 分辨率240*320"
|
||||
LCD Display Type
|
||||
config AUDIO_BOARD_LCD_JD9853
|
||||
bool "JD9853 320*172"
|
||||
config AUDIO_BOARD_LCD_ST7789
|
||||
bool "ST7789 240*320"
|
||||
endchoice
|
||||
|
||||
config USE_WECHAT_MESSAGE_STYLE
|
||||
bool "Enable WeChat Message Style"
|
||||
default n
|
||||
choice DISPLAY_STYLE
|
||||
prompt "Select display style"
|
||||
default USE_DEFAULT_MESSAGE_STYLE
|
||||
help
|
||||
使用微信聊天界面风格
|
||||
Select display style for Xiaozhi device
|
||||
|
||||
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_DEFAULT_MESSAGE_STYLE
|
||||
bool "Enable default message style"
|
||||
|
||||
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_WECHAT_MESSAGE_STYLE
|
||||
bool "Enable WeChat Message Style"
|
||||
|
||||
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)
|
||||
config USE_EMOTE_MESSAGE_STYLE
|
||||
bool "Emote animation style"
|
||||
depends on BOARD_TYPE_ESP_BOX || BOARD_TYPE_ESP_BOX_3 \
|
||||
|| BOARD_TYPE_ECHOEAR || BOARD_TYPE_LICHUANG_DEV_S3 \
|
||||
|| BOARD_TYPE_ESP_SENSAIRSHUTTLE
|
||||
endchoice
|
||||
|
||||
choice WAKE_WORD_TYPE
|
||||
prompt "Wake Word Implementation Type"
|
||||
default USE_AFE_WAKE_WORD if (IDF_TARGET_ESP32S3 || IDF_TARGET_ESP32P4) && SPIRAM
|
||||
default WAKE_WORD_DISABLED
|
||||
help
|
||||
需要 ESP32 S3 与 PSRAM 支持
|
||||
|
||||
Choose the type of wake word implementation to use
|
||||
|
||||
config WAKE_WORD_DISABLED
|
||||
bool "Disabled"
|
||||
help
|
||||
Disable wake word detection
|
||||
|
||||
config USE_ESP_WAKE_WORD
|
||||
bool "Wakenet model without AFE"
|
||||
depends on IDF_TARGET_ESP32C3 || IDF_TARGET_ESP32C5 || IDF_TARGET_ESP32C6 || (IDF_TARGET_ESP32 && SPIRAM)
|
||||
help
|
||||
Support ESP32 C3、ESP32 C5 与 ESP32 C6, and (ESP32 with PSRAM)
|
||||
|
||||
config USE_AFE_WAKE_WORD
|
||||
bool "Wakenet model with AFE"
|
||||
depends on (IDF_TARGET_ESP32S3 || IDF_TARGET_ESP32P4) && SPIRAM
|
||||
help
|
||||
Support AEC if available, requires ESP32 S3 and PSRAM
|
||||
|
||||
config USE_CUSTOM_WAKE_WORD
|
||||
bool "Multinet model (Custom Wake Word)"
|
||||
depends on (IDF_TARGET_ESP32S3 || IDF_TARGET_ESP32P4) && SPIRAM
|
||||
help
|
||||
Requires ESP32 S3 and PSRAM
|
||||
|
||||
endchoice
|
||||
|
||||
config CUSTOM_WAKE_WORD
|
||||
string "Custom Wake Word"
|
||||
default "xiao tu dou"
|
||||
depends on USE_CUSTOM_WAKE_WORD
|
||||
help
|
||||
自定义唤醒词,中文用拼音表示,每个字之间用空格隔开
|
||||
Custom Wake Word, use pinyin for Chinese, separated by spaces
|
||||
|
||||
config CUSTOM_WAKE_WORD_DISPLAY
|
||||
string "Custom Wake Word Display"
|
||||
default "小土豆"
|
||||
depends on USE_CUSTOM_WAKE_WORD
|
||||
help
|
||||
唤醒后发送给服务器的问候语
|
||||
Greeting sent to the server after wake word detection
|
||||
|
||||
config CUSTOM_WAKE_WORD_THRESHOLD
|
||||
int "Custom Wake Word Threshold (%)"
|
||||
@@ -496,64 +675,190 @@ config CUSTOM_WAKE_WORD_THRESHOLD
|
||||
range 1 99
|
||||
depends on USE_CUSTOM_WAKE_WORD
|
||||
help
|
||||
自定义唤醒词阈值,范围1-99,越小越敏感,默认10
|
||||
Custom Wake Word Threshold, range 1-99, the smaller the more sensitive, default 20
|
||||
|
||||
config SEND_WAKE_WORD_DATA
|
||||
bool "Send Wake Word Data"
|
||||
default y
|
||||
depends on USE_AFE_WAKE_WORD || USE_CUSTOM_WAKE_WORD
|
||||
help
|
||||
Send wake word data to the server as the first message of the conversation and wait for response
|
||||
|
||||
config WAKE_WORD_DETECTION_IN_LISTENING
|
||||
bool "Enable Wake Word Detection in Listening Mode"
|
||||
default n
|
||||
depends on USE_AFE_WAKE_WORD || USE_CUSTOM_WAKE_WORD
|
||||
help
|
||||
Enable wake word detection while in listening mode.
|
||||
When enabled, the device can detect wake word during listening,
|
||||
which allows interrupting the current conversation.
|
||||
When disabled (default), wake word detection is turned off during listening.
|
||||
|
||||
config USE_AUDIO_PROCESSOR
|
||||
bool "Enable Audio Noise Reduction"
|
||||
default y
|
||||
depends on (IDF_TARGET_ESP32S3 || IDF_TARGET_ESP32P4) && SPIRAM
|
||||
help
|
||||
需要 ESP32 S3 与 PSRAM 支持
|
||||
Requires ESP32 S3 and 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)
|
||||
depends on USE_AUDIO_PROCESSOR && (BOARD_TYPE_ESP_BOX_3 || BOARD_TYPE_ESP_BOX || BOARD_TYPE_ESP_BOX_LITE \
|
||||
|| BOARD_TYPE_LICHUANG_DEV_S3 || BOARD_TYPE_ESP_KORVO2_V3 || BOARD_TYPE_WAVESHARE_ESP32_S3_TOUCH_AMOLED_1_75 || BOARD_TYPE_WAVESHARE_ESP32_S3_TOUCH_LCD_1_83\
|
||||
|| BOARD_TYPE_WAVESHARE_ESP32_S3_TOUCH_AMOLED_2_06 || BOARD_TYPE_WAVESHARE_ESP32_S3_TOUCH_LCD_4B || BOARD_TYPE_WAVESHARE_ESP32_P4_WIFI6_TOUCH_LCD_4B || BOARD_TYPE_WAVESHARE_ESP32_P4_WIFI6_TOUCH_LCD_7B \
|
||||
|| BOARD_TYPE_WAVESHARE_ESP32_P4_WIFI6_TOUCH_LCD_3_4C || BOARD_TYPE_WAVESHARE_ESP32_P4_WIFI6_TOUCH_LCD_4C || BOARD_TYPE_ESP_S3_LCD_EV_Board_2 || BOARD_TYPE_YUNLIAO_S3 \
|
||||
|| BOARD_TYPE_WAVESHARE_ESP32_P4_WIFI6_TOUCH_LCD_7 || BOARD_TYPE_WAVESHARE_ESP32_P4_WIFI6_TOUCH_LCD_8 || BOARD_TYPE_WAVESHARE_ESP32_P4_WIFI6_TOUCH_LCD_10_1 \
|
||||
|| BOARD_TYPE_ECHOEAR || BOARD_TYPE_WAVESHARE_ESP32_S3_TOUCH_LCD_3_49 || BOARD_TYPE_WAVESHARE_ESP32_S3_RLCD_4_2 || BOARD_TYPE_ZHENGCHEN_CAM || BOARD_TYPE_ZHENGCHEN_CAM_ML307 \
|
||||
|| BOARD_TYPE_WAVESHARE_ESP32_S3_TOUCH_LCD_4_3C)
|
||||
help
|
||||
因为性能不够,不建议和微信聊天界面风格同时开启
|
||||
To work properly, device-side AEC requires a clean output reference path from the speaker signal and physical acoustic isolation between the microphone and speaker.
|
||||
|
||||
config USE_SERVER_AEC
|
||||
bool "Enable Server-Side AEC (Unstable)"
|
||||
default n
|
||||
depends on USE_AUDIO_PROCESSOR
|
||||
help
|
||||
启用服务器端 AEC,需要服务器支持
|
||||
To work perperly, server-side AEC requires server support
|
||||
|
||||
config USE_AUDIO_DEBUGGER
|
||||
bool "Enable Audio Debugger"
|
||||
default n
|
||||
help
|
||||
启用音频调试功能,通过UDP发送音频数据
|
||||
Enable audio debugger, send audio data through UDP to the host machine
|
||||
|
||||
config USE_ACOUSTIC_WIFI_PROVISIONING
|
||||
bool "Enable Acoustic WiFi Provisioning"
|
||||
default n
|
||||
menu "WiFi Configuration Method"
|
||||
help
|
||||
启用声波配网功能,使用音频信号传输 WiFi 配置数据
|
||||
WiFi Configuration Method Selection
|
||||
config USE_HOTSPOT_WIFI_PROVISIONING
|
||||
bool "Hotspot"
|
||||
default y
|
||||
help
|
||||
Use WiFi Hotspot to transmit WiFi configuration data
|
||||
config USE_ACOUSTIC_WIFI_PROVISIONING
|
||||
bool "Acoustic"
|
||||
help
|
||||
Use audio signal to transmit WiFi configuration data
|
||||
|
||||
config USE_ESP_BLUFI_WIFI_PROVISIONING
|
||||
bool "Esp Blufi"
|
||||
help
|
||||
Use esp blufi protocol to transmit WiFi configuration data
|
||||
select BT_ENABLED
|
||||
select BT_BLE_42_FEATURES_SUPPORTED
|
||||
select BT_BLE_BLUFI_ENABLE
|
||||
select MBEDTLS_DHM_C
|
||||
endmenu
|
||||
|
||||
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,用于接收音频调试数据
|
||||
UDP server address, format: IP:PORT, used to receive audio debugging data
|
||||
|
||||
config RECEIVE_CUSTOM_MESSAGE
|
||||
bool "Enable Custom Message Reception"
|
||||
default n
|
||||
help
|
||||
启用接收自定义消息功能,允许设备接收来自服务器的自定义消息(最好通过 MQTT 协议)
|
||||
Enable custom message reception, allow the device to receive custom messages from the server (preferably through the MQTT protocol)
|
||||
|
||||
choice I2S_TYPE_TAIJIPI_S3
|
||||
depends on BOARD_TYPE_ESP32S3_Taiji_Pi
|
||||
prompt "taiji-pi-S3 I2S Type"
|
||||
default TAIJIPAI_I2S_TYPE_STD
|
||||
menu "Camera Configuration"
|
||||
depends on !IDF_TARGET_ESP32
|
||||
|
||||
comment "Warning: Please read the help text before modifying these settings."
|
||||
|
||||
config XIAOZHI_CAMERA_ALLOW_JPEG_INPUT
|
||||
bool "Allow JPEG Input"
|
||||
default n
|
||||
help
|
||||
Allow JPEG Input format for the camera.
|
||||
|
||||
This option may need to be enabled when using a USB camera.
|
||||
|
||||
Not currently supported when used simultaneously with XIAOZHI_ENABLE_ROTATE_CAMERA_IMAGE.
|
||||
|
||||
config XIAOZHI_ENABLE_HARDWARE_JPEG_ENCODER
|
||||
bool "Enable Hardware JPEG Encoder"
|
||||
default y
|
||||
depends on SOC_JPEG_ENCODE_SUPPORTED
|
||||
help
|
||||
Use hardware JPEG encoder on ESP32-P4 to encode image to JPEG.
|
||||
See https://docs.espressif.com/projects/esp-idf/en/stable/esp32p4/api-reference/peripherals/jpeg.html for more details.
|
||||
|
||||
config XIAOZHI_ENABLE_HARDWARE_JPEG_DECODER
|
||||
bool "Enable Hardware JPEG Decoder"
|
||||
default n
|
||||
depends on SOC_JPEG_DECODE_SUPPORTED && XIAOZHI_CAMERA_ALLOW_JPEG_INPUT
|
||||
help
|
||||
Use hardware JPEG decoder on ESP32-P4 to decode JPEG to image.
|
||||
See https://docs.espressif.com/projects/esp-idf/en/stable/esp32p4/api-reference/peripherals/jpeg.html for more details.
|
||||
|
||||
config XIAOZHI_ENABLE_CAMERA_DEBUG_MODE
|
||||
bool "Enable Camera Debug Mode"
|
||||
default n
|
||||
help
|
||||
Enable camera debug mode, print camera debug information to the console.
|
||||
Only works on boards that support camera.
|
||||
|
||||
config XIAOZHI_ENABLE_CAMERA_ENDIANNESS_SWAP
|
||||
bool "Enable software camera buffer endianness swapping"
|
||||
default n
|
||||
depends on !CAMERA_SENSOR_SWAP_PIXEL_BYTE_ORDER
|
||||
help
|
||||
This option treats the camera buffer as a uint16_t[] array and performs byte-swapping (endianness conversion) on each element.
|
||||
|
||||
Should only be modified by development board integration engineers.
|
||||
|
||||
**Incorrect usage may result in incorrect image colors!**
|
||||
|
||||
ATTENTION: If the option CAMERA_SENSOR_SWAP_PIXEL_BYTE_ORDER is available for your sensor, please use that instead.
|
||||
|
||||
menuconfig XIAOZHI_ENABLE_ROTATE_CAMERA_IMAGE
|
||||
bool "Enable Camera Image Rotation"
|
||||
default n
|
||||
depends on !XIAOZHI_CAMERA_ALLOW_JPEG_INPUT
|
||||
help
|
||||
Enable camera image rotation, rotate the camera image to the correct orientation.
|
||||
- On ESP32-P4, rotation is handled by PPA hardware.
|
||||
- On other chips, rotation is done in software with performance cost.
|
||||
- For 180° rotation, use HFlip + VFlip instead of this option.
|
||||
|
||||
Not currently supported when used simultaneously with XIAOZHI_CAMERA_ALLOW_JPEG_INPUT.
|
||||
|
||||
if XIAOZHI_ENABLE_ROTATE_CAMERA_IMAGE
|
||||
choice XIAOZHI_CAMERA_IMAGE_ROTATION_ANGLE
|
||||
prompt "Camera Image Rotation Angle (clockwise)"
|
||||
default XIAOZHI_CAMERA_IMAGE_ROTATION_ANGLE_90
|
||||
help
|
||||
Camera image rotation angle.
|
||||
config XIAOZHI_CAMERA_IMAGE_ROTATION_ANGLE_90
|
||||
bool "90°"
|
||||
config XIAOZHI_CAMERA_IMAGE_ROTATION_ANGLE_270
|
||||
bool "270°"
|
||||
comment "For 180° rotation, use HFlip + VFlip instead of this option"
|
||||
endchoice
|
||||
endif
|
||||
endmenu
|
||||
|
||||
menu "TAIJIPAI_S3_CONFIG"
|
||||
depends on BOARD_TYPE_TAIJI_PI_S3
|
||||
choice I2S_TYPE_TAIJIPI_S3
|
||||
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
|
||||
|
||||
config I2S_USE_2SLOT
|
||||
bool "Enable I2S 2 Slot"
|
||||
default y
|
||||
help
|
||||
I2S 类型选择
|
||||
config TAIJIPAI_I2S_TYPE_STD
|
||||
bool "I2S Type STD"
|
||||
config TAIJIPAI_I2S_TYPE_PDM
|
||||
bool "I2S Type PDM"
|
||||
endchoice
|
||||
启动双声道
|
||||
endmenu
|
||||
|
||||
endmenu
|
||||
|
||||
1219
main/application.cc
1219
main/application.cc
File diff suppressed because it is too large
Load Diff
@@ -14,16 +14,23 @@
|
||||
#include "protocol.h"
|
||||
#include "ota.h"
|
||||
#include "audio_service.h"
|
||||
#include "device_state_event.h"
|
||||
#include "device_state.h"
|
||||
#include "device_state_machine.h"
|
||||
|
||||
|
||||
#define MAIN_EVENT_SCHEDULE (1 << 0)
|
||||
#define MAIN_EVENT_SEND_AUDIO (1 << 1)
|
||||
#define MAIN_EVENT_WAKE_WORD_DETECTED (1 << 2)
|
||||
#define MAIN_EVENT_VAD_CHANGE (1 << 3)
|
||||
#define MAIN_EVENT_ERROR (1 << 4)
|
||||
#define MAIN_EVENT_CHECK_NEW_VERSION_DONE (1 << 5)
|
||||
#define MAIN_EVENT_CLOCK_TICK (1 << 6)
|
||||
// Main event bits
|
||||
#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_ACTIVATION_DONE (1 << 5)
|
||||
#define MAIN_EVENT_CLOCK_TICK (1 << 6)
|
||||
#define MAIN_EVENT_NETWORK_CONNECTED (1 << 7)
|
||||
#define MAIN_EVENT_NETWORK_DISCONNECTED (1 << 8)
|
||||
#define MAIN_EVENT_TOGGLE_CHAT (1 << 9)
|
||||
#define MAIN_EVENT_START_LISTENING (1 << 10)
|
||||
#define MAIN_EVENT_STOP_LISTENING (1 << 11)
|
||||
#define MAIN_EVENT_STATE_CHANGED (1 << 12)
|
||||
|
||||
|
||||
enum AecMode {
|
||||
@@ -38,30 +45,80 @@ public:
|
||||
static Application instance;
|
||||
return instance;
|
||||
}
|
||||
// 删除拷贝构造函数和赋值运算符
|
||||
// Delete copy constructor and assignment operator
|
||||
Application(const Application&) = delete;
|
||||
Application& operator=(const Application&) = delete;
|
||||
|
||||
void Start();
|
||||
void MainEventLoop();
|
||||
DeviceState GetDeviceState() const { return device_state_; }
|
||||
/**
|
||||
* Initialize the application
|
||||
* This sets up display, audio, network callbacks, etc.
|
||||
* Network connection starts asynchronously.
|
||||
*/
|
||||
void Initialize();
|
||||
|
||||
/**
|
||||
* Run the main event loop
|
||||
* This function runs in the main task and never returns.
|
||||
* It handles all events including network, state changes, and user interactions.
|
||||
*/
|
||||
void Run();
|
||||
|
||||
DeviceState GetDeviceState() const { return state_machine_.GetState(); }
|
||||
bool IsVoiceDetected() const { return audio_service_.IsVoiceDetected(); }
|
||||
void Schedule(std::function<void()> callback);
|
||||
void SetDeviceState(DeviceState state);
|
||||
|
||||
/**
|
||||
* Request state transition
|
||||
* Returns true if transition was successful
|
||||
*/
|
||||
bool SetDeviceState(DeviceState state);
|
||||
|
||||
/**
|
||||
* Schedule a callback to be executed in the main task
|
||||
*/
|
||||
void Schedule(std::function<void()>&& callback);
|
||||
|
||||
/**
|
||||
* Alert with status, message, emotion and optional sound
|
||||
*/
|
||||
void Alert(const char* status, const char* message, const char* emotion = "", const std::string_view& sound = "");
|
||||
void DismissAlert();
|
||||
|
||||
void AbortSpeaking(AbortReason reason);
|
||||
|
||||
/**
|
||||
* Toggle chat state (event-based, thread-safe)
|
||||
* Sends MAIN_EVENT_TOGGLE_CHAT to be handled in Run()
|
||||
*/
|
||||
void ToggleChatState();
|
||||
|
||||
/**
|
||||
* Start listening (event-based, thread-safe)
|
||||
* Sends MAIN_EVENT_START_LISTENING to be handled in Run()
|
||||
*/
|
||||
void StartListening();
|
||||
|
||||
/**
|
||||
* Stop listening (event-based, thread-safe)
|
||||
* Sends MAIN_EVENT_STOP_LISTENING to be handled in Run()
|
||||
*/
|
||||
void StopListening();
|
||||
|
||||
void Reboot();
|
||||
void WakeWordInvoke(const std::string& wake_word);
|
||||
bool UpgradeFirmware(const std::string& url, const std::string& version = "");
|
||||
bool CanEnterSleepMode();
|
||||
void SendMcpMessage(const std::string& payload);
|
||||
void SetAecMode(AecMode mode);
|
||||
AecMode GetAecMode() const { return aec_mode_; }
|
||||
void PlaySound(const std::string_view& sound);
|
||||
AudioService& GetAudioService() { return audio_service_; }
|
||||
|
||||
/**
|
||||
* Reset protocol resources (thread-safe)
|
||||
* Can be called from any task to release resources allocated after network connected
|
||||
* This includes closing audio channel, resetting protocol and ota objects
|
||||
*/
|
||||
void ResetProtocol();
|
||||
|
||||
private:
|
||||
Application();
|
||||
@@ -72,21 +129,61 @@ private:
|
||||
std::unique_ptr<Protocol> protocol_;
|
||||
EventGroupHandle_t event_group_ = nullptr;
|
||||
esp_timer_handle_t clock_timer_handle_ = nullptr;
|
||||
volatile DeviceState device_state_ = kDeviceStateUnknown;
|
||||
DeviceStateMachine state_machine_;
|
||||
ListeningMode listening_mode_ = kListeningModeAutoStop;
|
||||
AecMode aec_mode_ = kAecOff;
|
||||
std::string last_error_message_;
|
||||
AudioService audio_service_;
|
||||
std::unique_ptr<Ota> ota_;
|
||||
|
||||
bool has_server_time_ = false;
|
||||
bool aborted_ = false;
|
||||
bool assets_version_checked_ = false;
|
||||
bool play_popup_on_listening_ = false; // Flag to play popup sound after state changes to listening
|
||||
int clock_ticks_ = 0;
|
||||
TaskHandle_t check_new_version_task_handle_ = nullptr;
|
||||
TaskHandle_t activation_task_handle_ = nullptr;
|
||||
|
||||
void OnWakeWordDetected();
|
||||
void CheckNewVersion(Ota& ota);
|
||||
|
||||
// Event handlers
|
||||
void HandleStateChangedEvent();
|
||||
void HandleToggleChatEvent();
|
||||
void HandleStartListeningEvent();
|
||||
void HandleStopListeningEvent();
|
||||
void HandleNetworkConnectedEvent();
|
||||
void HandleNetworkDisconnectedEvent();
|
||||
void HandleActivationDoneEvent();
|
||||
void HandleWakeWordDetectedEvent();
|
||||
void ContinueOpenAudioChannel(ListeningMode mode);
|
||||
void ContinueWakeWordInvoke(const std::string& wake_word);
|
||||
|
||||
// Activation task (runs in background)
|
||||
void ActivationTask();
|
||||
|
||||
// Helper methods
|
||||
void CheckAssetsVersion();
|
||||
void CheckNewVersion();
|
||||
void InitializeProtocol();
|
||||
void ShowActivationCode(const std::string& code, const std::string& message);
|
||||
void SetListeningMode(ListeningMode mode);
|
||||
ListeningMode GetDefaultListeningMode() const;
|
||||
|
||||
// State change handler called by state machine
|
||||
void OnStateChanged(DeviceState old_state, DeviceState new_state);
|
||||
};
|
||||
|
||||
|
||||
class TaskPriorityReset {
|
||||
public:
|
||||
TaskPriorityReset(BaseType_t priority) {
|
||||
original_priority_ = uxTaskPriorityGet(NULL);
|
||||
vTaskPrioritySet(NULL, priority);
|
||||
}
|
||||
~TaskPriorityReset() {
|
||||
vTaskPrioritySet(NULL, original_priority_);
|
||||
}
|
||||
|
||||
private:
|
||||
BaseType_t original_priority_;
|
||||
};
|
||||
|
||||
#endif // _APPLICATION_H_
|
||||
|
||||
560
main/assets.cc
Normal file
560
main/assets.cc
Normal file
@@ -0,0 +1,560 @@
|
||||
#include "assets.h"
|
||||
#include "board.h"
|
||||
#include "display.h"
|
||||
#include "application.h"
|
||||
#include "lvgl_theme.h"
|
||||
#include "emote_display.h"
|
||||
#include "expression_emote.h"
|
||||
#if HAVE_LVGL
|
||||
#include "display/lcd_display.h"
|
||||
#include <spi_flash_mmap.h>
|
||||
#endif
|
||||
|
||||
#include <esp_log.h>
|
||||
#include <esp_timer.h>
|
||||
#include <esp_heap_caps.h>
|
||||
#include <cbin_font.h>
|
||||
|
||||
|
||||
#define TAG "Assets"
|
||||
#define PARTITION_LABEL "assets"
|
||||
|
||||
struct mmap_assets_table {
|
||||
char asset_name[32]; /*!< Name of the asset */
|
||||
uint32_t asset_size; /*!< Size of the asset */
|
||||
uint32_t asset_offset; /*!< Offset of the asset */
|
||||
uint16_t asset_width; /*!< Width of the asset */
|
||||
uint16_t asset_height; /*!< Height of the asset */
|
||||
};
|
||||
|
||||
Assets::Assets() {
|
||||
#if HAVE_LVGL
|
||||
strategy_ = std::make_unique<Assets::LvglStrategy>();
|
||||
#else
|
||||
strategy_ = std::make_unique<Assets::EmoteStrategy>();
|
||||
#endif
|
||||
// Initialize the partition
|
||||
InitializePartition();
|
||||
}
|
||||
|
||||
Assets::~Assets() {
|
||||
UnApplyPartition();
|
||||
}
|
||||
|
||||
bool Assets::FindPartition(Assets* assets) {
|
||||
assets->partition_ = esp_partition_find_first(ESP_PARTITION_TYPE_ANY, ESP_PARTITION_SUBTYPE_ANY, PARTITION_LABEL);
|
||||
if (assets->partition_ == nullptr) {
|
||||
ESP_LOGI(TAG, "No assets partition found");
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Assets::Apply() {
|
||||
return strategy_ ? strategy_->Apply(this) : false;
|
||||
}
|
||||
|
||||
bool Assets::InitializePartition() {
|
||||
return strategy_ ? strategy_->InitializePartition(this) : false;
|
||||
}
|
||||
|
||||
void Assets::UnApplyPartition() {
|
||||
if (strategy_) {
|
||||
strategy_->UnApplyPartition(this);
|
||||
}
|
||||
}
|
||||
|
||||
bool Assets::GetAssetData(const std::string& name, void*& ptr, size_t& size) {
|
||||
return strategy_ ? strategy_->GetAssetData(this, name, ptr, size) : false;
|
||||
}
|
||||
|
||||
bool Assets::LoadSrmodelsFromIndex(Assets* assets, cJSON* root) {
|
||||
void* ptr = nullptr;
|
||||
size_t size = 0;
|
||||
bool need_delete_root = false;
|
||||
|
||||
// If root is not provided, parse index.json
|
||||
if (root == nullptr) {
|
||||
if (!assets->GetAssetData("index.json", ptr, size)) {
|
||||
ESP_LOGE(TAG, "The index.json file is not found");
|
||||
return false;
|
||||
}
|
||||
|
||||
root = cJSON_ParseWithLength(static_cast<char*>(ptr), size);
|
||||
if (root == nullptr) {
|
||||
ESP_LOGE(TAG, "The index.json file is not valid");
|
||||
return false;
|
||||
}
|
||||
need_delete_root = true;
|
||||
}
|
||||
|
||||
cJSON* srmodels = cJSON_GetObjectItem(root, "srmodels");
|
||||
if (cJSON_IsString(srmodels)) {
|
||||
std::string srmodels_file = srmodels->valuestring;
|
||||
if (assets->GetAssetData(srmodels_file, ptr, size)) {
|
||||
if (assets->models_list_ != nullptr) {
|
||||
esp_srmodel_deinit(assets->models_list_);
|
||||
assets->models_list_ = nullptr;
|
||||
}
|
||||
assets->models_list_ = srmodel_load(static_cast<uint8_t*>(ptr));
|
||||
if (assets->models_list_ != nullptr) {
|
||||
auto& app = Application::GetInstance();
|
||||
app.GetAudioService().SetModelsList(assets->models_list_);
|
||||
if (need_delete_root) {
|
||||
cJSON_Delete(root);
|
||||
}
|
||||
return true;
|
||||
} else {
|
||||
ESP_LOGE(TAG, "Failed to load srmodels.bin");
|
||||
}
|
||||
} else {
|
||||
ESP_LOGE(TAG, "The srmodels file %s is not found", srmodels_file.c_str());
|
||||
}
|
||||
}
|
||||
|
||||
if (need_delete_root) {
|
||||
cJSON_Delete(root);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
#if HAVE_LVGL
|
||||
uint32_t Assets::LvglStrategy::CalculateChecksum(const char* data, uint32_t length) {
|
||||
uint32_t checksum = 0;
|
||||
for (uint32_t i = 0; i < length; i++) {
|
||||
checksum += data[i];
|
||||
}
|
||||
return checksum & 0xFFFF;
|
||||
}
|
||||
|
||||
bool Assets::LvglStrategy::InitializePartition(Assets* assets) {
|
||||
assets->partition_valid_ = false;
|
||||
assets_.clear();
|
||||
|
||||
if (!Assets::FindPartition(assets)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
int free_pages = spi_flash_mmap_get_free_pages(SPI_FLASH_MMAP_DATA);
|
||||
uint32_t storage_size = free_pages * 64 * 1024;
|
||||
ESP_LOGI(TAG, "The storage free size is %ld KB", storage_size / 1024);
|
||||
ESP_LOGI(TAG, "The partition size is %ld KB", assets->partition_->size / 1024);
|
||||
if (storage_size < assets->partition_->size) {
|
||||
ESP_LOGE(TAG, "The free size %ld KB is less than assets partition required %ld KB", storage_size / 1024, assets->partition_->size / 1024);
|
||||
return false;
|
||||
}
|
||||
|
||||
esp_err_t err = esp_partition_mmap(assets->partition_, 0, assets->partition_->size, ESP_PARTITION_MMAP_DATA, (const void**)&mmap_root_, &mmap_handle_);
|
||||
if (err != ESP_OK) {
|
||||
ESP_LOGE(TAG, "Failed to mmap assets partition: %s", esp_err_to_name(err));
|
||||
return false;
|
||||
}
|
||||
|
||||
assets->partition_valid_ = true;
|
||||
|
||||
uint32_t stored_files = *(uint32_t*)(mmap_root_ + 0);
|
||||
uint32_t stored_chksum = *(uint32_t*)(mmap_root_ + 4);
|
||||
uint32_t stored_len = *(uint32_t*)(mmap_root_ + 8);
|
||||
|
||||
if (stored_len > assets->partition_->size - 12) {
|
||||
ESP_LOGD(TAG, "The stored_len (0x%lx) is greater than the partition size (0x%lx) - 12", stored_len, assets->partition_->size);
|
||||
return false;
|
||||
}
|
||||
|
||||
auto start_time = esp_timer_get_time();
|
||||
uint32_t calculated_checksum = CalculateChecksum(mmap_root_ + 12, stored_len);
|
||||
auto end_time = esp_timer_get_time();
|
||||
ESP_LOGI(TAG, "The checksum calculation time is %d ms", int((end_time - start_time) / 1000));
|
||||
|
||||
if (calculated_checksum != stored_chksum) {
|
||||
ESP_LOGE(TAG, "The calculated checksum (0x%lx) does not match the stored checksum (0x%lx)", calculated_checksum, stored_chksum);
|
||||
return false;
|
||||
}
|
||||
|
||||
checksum_valid_ = true;
|
||||
|
||||
for (uint32_t i = 0; i < stored_files; i++) {
|
||||
auto item = (const mmap_assets_table*)(mmap_root_ + 12 + i * sizeof(mmap_assets_table));
|
||||
auto asset = Asset{
|
||||
.size = static_cast<size_t>(item->asset_size),
|
||||
.offset = static_cast<size_t>(12 + sizeof(mmap_assets_table) * stored_files + item->asset_offset)
|
||||
};
|
||||
assets_[item->asset_name] = asset;
|
||||
}
|
||||
return checksum_valid_;
|
||||
}
|
||||
|
||||
void Assets::LvglStrategy::UnApplyPartition(Assets* assets) {
|
||||
if (mmap_handle_ != 0) {
|
||||
esp_partition_munmap(mmap_handle_);
|
||||
mmap_handle_ = 0;
|
||||
mmap_root_ = nullptr;
|
||||
}
|
||||
checksum_valid_ = false;
|
||||
assets_.clear();
|
||||
(void)assets; // Unused parameter
|
||||
}
|
||||
|
||||
bool Assets::LvglStrategy::GetAssetData(Assets* assets, const std::string& name, void*& ptr, size_t& size) {
|
||||
auto asset = assets_.find(name);
|
||||
if (asset == assets_.end()) {
|
||||
return false;
|
||||
}
|
||||
auto data = (const char*)(mmap_root_ + asset->second.offset);
|
||||
if (data[0] != 'Z' || data[1] != 'Z') {
|
||||
ESP_LOGE(TAG, "The asset %s is not valid with magic %02x%02x", name.c_str(), data[0], data[1]);
|
||||
return false;
|
||||
}
|
||||
|
||||
ptr = static_cast<void*>(const_cast<char*>(data + 2));
|
||||
size = asset->second.size;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Assets::LvglStrategy::Apply(Assets* assets) {
|
||||
void* ptr = nullptr;
|
||||
size_t size = 0;
|
||||
if (!assets->GetAssetData("index.json", ptr, size)) {
|
||||
ESP_LOGE(TAG, "The index.json file is not found");
|
||||
return false;
|
||||
}
|
||||
|
||||
cJSON* root = cJSON_ParseWithLength(static_cast<char*>(ptr), size);
|
||||
if (root == nullptr) {
|
||||
ESP_LOGE(TAG, "The index.json file is not valid");
|
||||
return false;
|
||||
}
|
||||
|
||||
cJSON* version = cJSON_GetObjectItem(root, "version");
|
||||
if (cJSON_IsNumber(version)) {
|
||||
if (version->valuedouble > 1) {
|
||||
ESP_LOGE(TAG, "The assets version %d is not supported, please upgrade the firmware", version->valueint);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
Assets::LoadSrmodelsFromIndex(assets, root);
|
||||
|
||||
auto& theme_manager = LvglThemeManager::GetInstance();
|
||||
auto light_theme = theme_manager.GetTheme("light");
|
||||
auto dark_theme = theme_manager.GetTheme("dark");
|
||||
|
||||
cJSON* font = cJSON_GetObjectItem(root, "text_font");
|
||||
if (cJSON_IsString(font)) {
|
||||
std::string fonts_text_file = font->valuestring;
|
||||
if (assets->GetAssetData(fonts_text_file, ptr, size)) {
|
||||
auto text_font = std::make_shared<LvglCBinFont>(ptr);
|
||||
if (text_font->font() == nullptr) {
|
||||
ESP_LOGE(TAG, "Failed to load fonts.bin");
|
||||
return false;
|
||||
}
|
||||
if (light_theme != nullptr) {
|
||||
light_theme->set_text_font(text_font);
|
||||
}
|
||||
if (dark_theme != nullptr) {
|
||||
dark_theme->set_text_font(text_font);
|
||||
}
|
||||
} else {
|
||||
ESP_LOGE(TAG, "The font file %s is not found", fonts_text_file.c_str());
|
||||
}
|
||||
}
|
||||
|
||||
cJSON* emoji_collection = cJSON_GetObjectItem(root, "emoji_collection");
|
||||
if (cJSON_IsArray(emoji_collection)) {
|
||||
auto custom_emoji_collection = std::make_shared<EmojiCollection>();
|
||||
int emoji_count = cJSON_GetArraySize(emoji_collection);
|
||||
for (int i = 0; i < emoji_count; i++) {
|
||||
cJSON* emoji = cJSON_GetArrayItem(emoji_collection, i);
|
||||
if (cJSON_IsObject(emoji)) {
|
||||
cJSON* name = cJSON_GetObjectItem(emoji, "name");
|
||||
cJSON* file = cJSON_GetObjectItem(emoji, "file");
|
||||
cJSON* eaf = cJSON_GetObjectItem(emoji, "eaf");
|
||||
if (cJSON_IsString(name) && cJSON_IsString(file) && (NULL== eaf)) {
|
||||
if (!assets->GetAssetData(file->valuestring, ptr, size)) {
|
||||
ESP_LOGE(TAG, "Emoji %s image file %s is not found", name->valuestring, file->valuestring);
|
||||
continue;
|
||||
}
|
||||
custom_emoji_collection->AddEmoji(name->valuestring, new LvglRawImage(ptr, size));
|
||||
}
|
||||
}
|
||||
}
|
||||
if (light_theme != nullptr) {
|
||||
light_theme->set_emoji_collection(custom_emoji_collection);
|
||||
}
|
||||
if (dark_theme != nullptr) {
|
||||
dark_theme->set_emoji_collection(custom_emoji_collection);
|
||||
}
|
||||
}
|
||||
|
||||
cJSON* skin = cJSON_GetObjectItem(root, "skin");
|
||||
if (cJSON_IsObject(skin)) {
|
||||
cJSON* light_skin = cJSON_GetObjectItem(skin, "light");
|
||||
if (cJSON_IsObject(light_skin) && light_theme != nullptr) {
|
||||
cJSON* text_color = cJSON_GetObjectItem(light_skin, "text_color");
|
||||
cJSON* background_color = cJSON_GetObjectItem(light_skin, "background_color");
|
||||
cJSON* background_image = cJSON_GetObjectItem(light_skin, "background_image");
|
||||
if (cJSON_IsString(text_color)) {
|
||||
light_theme->set_text_color(LvglTheme::ParseColor(text_color->valuestring));
|
||||
}
|
||||
if (cJSON_IsString(background_color)) {
|
||||
light_theme->set_background_color(LvglTheme::ParseColor(background_color->valuestring));
|
||||
light_theme->set_chat_background_color(LvglTheme::ParseColor(background_color->valuestring));
|
||||
}
|
||||
if (cJSON_IsString(background_image)) {
|
||||
if (!assets->GetAssetData(background_image->valuestring, ptr, size)) {
|
||||
ESP_LOGE(TAG, "The background image file %s is not found", background_image->valuestring);
|
||||
return false;
|
||||
}
|
||||
auto background_image = std::make_shared<LvglCBinImage>(ptr);
|
||||
light_theme->set_background_image(background_image);
|
||||
}
|
||||
}
|
||||
cJSON* dark_skin = cJSON_GetObjectItem(skin, "dark");
|
||||
if (cJSON_IsObject(dark_skin) && dark_theme != nullptr) {
|
||||
cJSON* text_color = cJSON_GetObjectItem(dark_skin, "text_color");
|
||||
cJSON* background_color = cJSON_GetObjectItem(dark_skin, "background_color");
|
||||
cJSON* background_image = cJSON_GetObjectItem(dark_skin, "background_image");
|
||||
if (cJSON_IsString(text_color)) {
|
||||
dark_theme->set_text_color(LvglTheme::ParseColor(text_color->valuestring));
|
||||
}
|
||||
if (cJSON_IsString(background_color)) {
|
||||
dark_theme->set_background_color(LvglTheme::ParseColor(background_color->valuestring));
|
||||
dark_theme->set_chat_background_color(LvglTheme::ParseColor(background_color->valuestring));
|
||||
}
|
||||
if (cJSON_IsString(background_image)) {
|
||||
if (!assets->GetAssetData(background_image->valuestring, ptr, size)) {
|
||||
ESP_LOGE(TAG, "The background image file %s is not found", background_image->valuestring);
|
||||
return false;
|
||||
}
|
||||
auto background_image = std::make_shared<LvglCBinImage>(ptr);
|
||||
dark_theme->set_background_image(background_image);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
auto display = Board::GetInstance().GetDisplay();
|
||||
ESP_LOGI(TAG, "Refreshing display theme...");
|
||||
|
||||
auto current_theme = display->GetTheme();
|
||||
if (current_theme != nullptr) {
|
||||
display->SetTheme(current_theme);
|
||||
}
|
||||
|
||||
// Parse hide_subtitle configuration
|
||||
cJSON* hide_subtitle = cJSON_GetObjectItem(root, "hide_subtitle");
|
||||
if (cJSON_IsBool(hide_subtitle)) {
|
||||
bool hide = cJSON_IsTrue(hide_subtitle);
|
||||
auto lcd_display = dynamic_cast<LcdDisplay*>(display);
|
||||
if (lcd_display != nullptr) {
|
||||
lcd_display->SetHideSubtitle(hide);
|
||||
ESP_LOGI(TAG, "Set hide_subtitle to %s", hide ? "true" : "false");
|
||||
}
|
||||
}
|
||||
|
||||
cJSON_Delete(root);
|
||||
return true;
|
||||
}
|
||||
#endif // HAVE_LVGL
|
||||
|
||||
bool Assets::EmoteStrategy::InitializePartition(Assets* assets) {
|
||||
assets->partition_valid_ = false;
|
||||
|
||||
if (!Assets::FindPartition(assets)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
esp_err_t ret = ESP_ERR_INVALID_STATE;
|
||||
auto display = Board::GetInstance().GetDisplay();
|
||||
auto* emote_display = dynamic_cast<emote::EmoteDisplay*>(display);
|
||||
if (emote_display && emote_display->GetEmoteHandle() != nullptr) {
|
||||
const emote_data_t data = {
|
||||
.type = EMOTE_SOURCE_PARTITION,
|
||||
.source = {
|
||||
.partition_label = PARTITION_LABEL,
|
||||
},
|
||||
.flags = {
|
||||
.mmap_enable = true, //must be true here!!!
|
||||
},
|
||||
};
|
||||
ret = emote_mount_assets(emote_display->GetEmoteHandle(), &data);
|
||||
} else {
|
||||
ESP_LOGE(TAG, "Emote display is not initialized");
|
||||
}
|
||||
assets->partition_valid_ = ((ret == ESP_OK) ? true : false);
|
||||
return assets->partition_valid_;
|
||||
}
|
||||
|
||||
void Assets::EmoteStrategy::UnApplyPartition(Assets* assets) {
|
||||
auto display = Board::GetInstance().GetDisplay();
|
||||
auto* emote_display = dynamic_cast<emote::EmoteDisplay*>(display);
|
||||
if (emote_display && emote_display->GetEmoteHandle() != nullptr) {
|
||||
emote_unmount_assets(emote_display->GetEmoteHandle());
|
||||
}
|
||||
(void)assets; // Unused parameter
|
||||
}
|
||||
|
||||
bool Assets::EmoteStrategy::GetAssetData(Assets* assets, const std::string& name, void*& ptr, size_t& size) {
|
||||
auto display = Board::GetInstance().GetDisplay();
|
||||
auto* emote_display = dynamic_cast<emote::EmoteDisplay*>(display);
|
||||
if (emote_display && emote_display->GetEmoteHandle() != nullptr) {
|
||||
const uint8_t* data = nullptr;
|
||||
size_t data_size = 0;
|
||||
if (ESP_OK == emote_get_asset_data_by_name(emote_display->GetEmoteHandle(), name.c_str(), &data, &data_size)) {
|
||||
ptr = const_cast<void*>(static_cast<const void*>(data));
|
||||
size = data_size;
|
||||
return true;
|
||||
}
|
||||
ESP_LOGE(TAG, "Failed to get asset data by name: %s", name.c_str());
|
||||
return false;
|
||||
}
|
||||
(void)assets; // Unused parameter
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Assets::EmoteStrategy::Apply(Assets* assets) {
|
||||
Assets::LoadSrmodelsFromIndex(assets);
|
||||
|
||||
auto display = Board::GetInstance().GetDisplay();
|
||||
auto* emote_display = dynamic_cast<emote::EmoteDisplay*>(display);
|
||||
|
||||
if (emote_display && emote_display->GetEmoteHandle() != nullptr) {
|
||||
emote_load_assets(emote_display->GetEmoteHandle());
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Assets::Download(std::string url, std::function<void(int progress, size_t speed)> progress_callback) {
|
||||
ESP_LOGI(TAG, "Downloading new version of assets from %s", url.c_str());
|
||||
|
||||
// 取消当前资源分区的内存映射
|
||||
UnApplyPartition();
|
||||
|
||||
// 下载新的资源文件
|
||||
auto network = Board::GetInstance().GetNetwork();
|
||||
auto http = network->CreateHttp(0);
|
||||
|
||||
if (!http->Open("GET", url)) {
|
||||
ESP_LOGE(TAG, "Failed to open HTTP connection");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (http->GetStatusCode() != 200) {
|
||||
ESP_LOGE(TAG, "Failed to get assets, status code: %d", http->GetStatusCode());
|
||||
return false;
|
||||
}
|
||||
|
||||
size_t content_length = http->GetBodyLength();
|
||||
if (content_length == 0) {
|
||||
ESP_LOGE(TAG, "Failed to get content length");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (content_length > partition_->size) {
|
||||
ESP_LOGE(TAG, "Assets file size (%u) is larger than partition size (%lu)", content_length, partition_->size);
|
||||
return false;
|
||||
}
|
||||
|
||||
// 定义扇区大小为4KB(ESP32的标准扇区大小)
|
||||
const size_t SECTOR_SIZE = esp_partition_get_main_flash_sector_size();
|
||||
|
||||
// 计算需要擦除的扇区数量
|
||||
size_t sectors_to_erase = (content_length + SECTOR_SIZE - 1) / SECTOR_SIZE; // 向上取整
|
||||
size_t total_erase_size = sectors_to_erase * SECTOR_SIZE;
|
||||
|
||||
ESP_LOGI(TAG, "Sector size: %u, content length: %u, sectors to erase: %u, total erase size: %u",
|
||||
SECTOR_SIZE, content_length, sectors_to_erase, total_erase_size);
|
||||
|
||||
// 写入新的资源文件到分区,一边erase一边写入
|
||||
char* buffer = (char*)heap_caps_malloc(SECTOR_SIZE, MALLOC_CAP_INTERNAL);
|
||||
if (buffer == nullptr) {
|
||||
ESP_LOGE(TAG, "Failed to allocate buffer");
|
||||
return false;
|
||||
}
|
||||
size_t total_written = 0;
|
||||
size_t recent_written = 0;
|
||||
size_t current_sector = 0;
|
||||
auto last_calc_time = esp_timer_get_time();
|
||||
|
||||
while (true) {
|
||||
int ret = http->Read(buffer, SECTOR_SIZE);
|
||||
if (ret < 0) {
|
||||
ESP_LOGE(TAG, "Failed to read HTTP data: %s", esp_err_to_name(ret));
|
||||
heap_caps_free(buffer);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (ret == 0) {
|
||||
break;
|
||||
}
|
||||
|
||||
// 检查是否需要擦除新的扇区
|
||||
size_t write_end_offset = total_written + ret;
|
||||
size_t needed_sectors = (write_end_offset + SECTOR_SIZE - 1) / SECTOR_SIZE;
|
||||
|
||||
// 擦除需要的新扇区
|
||||
while (current_sector < needed_sectors) {
|
||||
size_t sector_start = current_sector * SECTOR_SIZE;
|
||||
size_t sector_end = (current_sector + 1) * SECTOR_SIZE;
|
||||
|
||||
// 确保擦除范围不超过分区大小
|
||||
if (sector_end > partition_->size) {
|
||||
ESP_LOGE(TAG, "Sector end (%u) exceeds partition size (%lu)", sector_end, partition_->size);
|
||||
heap_caps_free(buffer);
|
||||
return false;
|
||||
}
|
||||
|
||||
ESP_LOGD(TAG, "Erasing sector %u (offset: %u, size: %u)", current_sector, sector_start, SECTOR_SIZE);
|
||||
esp_err_t err = esp_partition_erase_range(partition_, sector_start, SECTOR_SIZE);
|
||||
if (err != ESP_OK) {
|
||||
ESP_LOGE(TAG, "Failed to erase sector %u at offset %u: %s", current_sector, sector_start, esp_err_to_name(err));
|
||||
heap_caps_free(buffer);
|
||||
return false;
|
||||
}
|
||||
|
||||
current_sector++;
|
||||
}
|
||||
|
||||
// 写入数据到分区
|
||||
esp_err_t err = esp_partition_write(partition_, total_written, buffer, ret);
|
||||
if (err != ESP_OK) {
|
||||
ESP_LOGE(TAG, "Failed to write to assets partition at offset %u: %s", total_written, esp_err_to_name(err));
|
||||
heap_caps_free(buffer);
|
||||
return false;
|
||||
}
|
||||
|
||||
total_written += ret;
|
||||
recent_written += ret;
|
||||
|
||||
// 计算进度和速度
|
||||
if (esp_timer_get_time() - last_calc_time >= 1000000 || total_written == content_length || ret == 0) {
|
||||
size_t progress = total_written * 100 / content_length;
|
||||
size_t speed = recent_written; // 每秒的字节数
|
||||
ESP_LOGI(TAG, "Progress: %u%% (%u/%u), Speed: %u B/s, Sectors erased: %u",
|
||||
progress, total_written, content_length, speed, current_sector);
|
||||
if (progress_callback) {
|
||||
progress_callback(progress, speed);
|
||||
}
|
||||
last_calc_time = esp_timer_get_time();
|
||||
recent_written = 0; // 重置最近写入的字节数
|
||||
}
|
||||
}
|
||||
|
||||
http->Close();
|
||||
heap_caps_free(buffer);
|
||||
|
||||
if (total_written != content_length) {
|
||||
ESP_LOGE(TAG, "Downloaded size (%u) does not match expected size (%u)", total_written, content_length);
|
||||
return false;
|
||||
}
|
||||
|
||||
ESP_LOGI(TAG, "Assets download completed, total written: %u bytes, total sectors erased: %u",
|
||||
total_written, current_sector);
|
||||
|
||||
// 重新初始化资源分区
|
||||
if (!InitializePartition()) {
|
||||
ESP_LOGE(TAG, "Failed to re-initialize assets partition");
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
89
main/assets.h
Normal file
89
main/assets.h
Normal file
@@ -0,0 +1,89 @@
|
||||
#ifndef ASSETS_H
|
||||
#define ASSETS_H
|
||||
|
||||
#include <string>
|
||||
#include <functional>
|
||||
#include <memory>
|
||||
|
||||
#include <cJSON.h>
|
||||
#include <esp_partition.h>
|
||||
#include <model_path.h>
|
||||
#include <map>
|
||||
#include <string>
|
||||
|
||||
#if HAVE_LVGL
|
||||
#include <spi_flash_mmap.h>
|
||||
#endif
|
||||
|
||||
struct Asset {
|
||||
size_t size;
|
||||
size_t offset;
|
||||
};
|
||||
|
||||
class Assets {
|
||||
public:
|
||||
static Assets& GetInstance() {
|
||||
static Assets instance;
|
||||
return instance;
|
||||
}
|
||||
~Assets();
|
||||
|
||||
bool Download(std::string url, std::function<void(int progress, size_t speed)> progress_callback);
|
||||
bool Apply();
|
||||
bool GetAssetData(const std::string& name, void*& ptr, size_t& size);
|
||||
|
||||
inline bool partition_valid() const { return partition_valid_; }
|
||||
inline std::string default_assets_url() const { return default_assets_url_; }
|
||||
|
||||
private:
|
||||
Assets();
|
||||
Assets(const Assets&) = delete;
|
||||
Assets& operator=(const Assets&) = delete;
|
||||
|
||||
bool InitializePartition();
|
||||
void UnApplyPartition();
|
||||
static bool FindPartition(Assets* assets);
|
||||
static bool LoadSrmodelsFromIndex(Assets* assets, cJSON* root = nullptr);
|
||||
|
||||
class AssetStrategy {
|
||||
public:
|
||||
virtual ~AssetStrategy() = default;
|
||||
virtual bool Apply(Assets* assets) = 0;
|
||||
virtual bool InitializePartition(Assets* assets) = 0;
|
||||
virtual void UnApplyPartition(Assets* assets) = 0;
|
||||
virtual bool GetAssetData(Assets* assets, const std::string& name, void*& ptr, size_t& size) = 0;
|
||||
};
|
||||
|
||||
class LvglStrategy : public AssetStrategy {
|
||||
public:
|
||||
bool Apply(Assets* assets) override;
|
||||
bool InitializePartition(Assets* assets) override;
|
||||
void UnApplyPartition(Assets* assets) override;
|
||||
bool GetAssetData(Assets* assets, const std::string& name, void*& ptr, size_t& size) override;
|
||||
private:
|
||||
static uint32_t CalculateChecksum(const char* data, uint32_t length);
|
||||
std::map<std::string, Asset> assets_;
|
||||
esp_partition_mmap_handle_t mmap_handle_ = 0;
|
||||
const char* mmap_root_ = nullptr;
|
||||
bool checksum_valid_ = false;
|
||||
};
|
||||
|
||||
class EmoteStrategy : public AssetStrategy {
|
||||
public:
|
||||
bool Apply(Assets* assets) override;
|
||||
bool InitializePartition(Assets* assets) override;
|
||||
void UnApplyPartition(Assets* assets) override;
|
||||
bool GetAssetData(Assets* assets, const std::string& name, void*& ptr, size_t& size) override;
|
||||
};
|
||||
|
||||
// Strategy instance
|
||||
std::unique_ptr<AssetStrategy> strategy_;
|
||||
|
||||
protected:
|
||||
const esp_partition_t* partition_ = nullptr;
|
||||
bool partition_valid_ = false;
|
||||
std::string default_assets_url_;
|
||||
srmodel_list_t* models_list_ = nullptr;
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -1,58 +1,59 @@
|
||||
{
|
||||
"language": {
|
||||
"type" :"ar-SA"
|
||||
"type": "ar-SA"
|
||||
},
|
||||
"strings": {
|
||||
"WARNING":"تحذير",
|
||||
"INFO":"معلومات",
|
||||
"ERROR":"خطأ",
|
||||
"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...",
|
||||
|
||||
"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 مُشغل"
|
||||
"OTA_UPGRADE": "تحديث OTA",
|
||||
"UPGRADING": "تحديث النظام...",
|
||||
"UPGRADE_FAILED": "فشل التحديث",
|
||||
"ACTIVATION": "تفعيل الجهاز",
|
||||
"BATTERY_LOW": "البطارية منخفضة",
|
||||
"BATTERY_CHARGING": "جاري الشحن",
|
||||
"BATTERY_FULL": "البطارية ممتلئة",
|
||||
"BATTERY_NEED_CHARGE": "البطارية منخفضة، يرجى الشحن",
|
||||
"VOLUME": "الصوت ",
|
||||
"MUTED": "صامت",
|
||||
"MAX_VOLUME": "أقصى صوت",
|
||||
"RTC_MODE_OFF": "AEC مُوقف",
|
||||
"RTC_MODE_ON": "AEC مُشغل",
|
||||
"DOWNLOAD_ASSETS_FAILED": "فشل في تنزيل الموارد",
|
||||
"LOADING_ASSETS": "جاري تحميل الموارد...",
|
||||
"PLEASE_WAIT": "يرجى الانتظار...",
|
||||
"FOUND_NEW_ASSETS": "تم العثور على موارد جديدة: %s",
|
||||
"HELLO_MY_FRIEND": "مرحباً، صديقي!",
|
||||
"CONNECTION_SUCCESSFUL": "تم الاتصال بنجاح",
|
||||
"FLIGHT_MODE_OFF": "وضع الطيران معطل",
|
||||
"FLIGHT_MODE_ON": "وضع الطيران قيد التشغيل",
|
||||
"MODEM_INIT_ERROR": "فشل تهيئة المودم"
|
||||
}
|
||||
}
|
||||
}
|
||||
BIN
main/assets/locales/bg-BG/0.ogg
Normal file
BIN
main/assets/locales/bg-BG/0.ogg
Normal file
Binary file not shown.
BIN
main/assets/locales/bg-BG/1.ogg
Normal file
BIN
main/assets/locales/bg-BG/1.ogg
Normal file
Binary file not shown.
BIN
main/assets/locales/bg-BG/2.ogg
Normal file
BIN
main/assets/locales/bg-BG/2.ogg
Normal file
Binary file not shown.
BIN
main/assets/locales/bg-BG/3.ogg
Normal file
BIN
main/assets/locales/bg-BG/3.ogg
Normal file
Binary file not shown.
BIN
main/assets/locales/bg-BG/4.ogg
Normal file
BIN
main/assets/locales/bg-BG/4.ogg
Normal file
Binary file not shown.
BIN
main/assets/locales/bg-BG/5.ogg
Normal file
BIN
main/assets/locales/bg-BG/5.ogg
Normal file
Binary file not shown.
BIN
main/assets/locales/bg-BG/6.ogg
Normal file
BIN
main/assets/locales/bg-BG/6.ogg
Normal file
Binary file not shown.
BIN
main/assets/locales/bg-BG/7.ogg
Normal file
BIN
main/assets/locales/bg-BG/7.ogg
Normal file
Binary file not shown.
BIN
main/assets/locales/bg-BG/8.ogg
Normal file
BIN
main/assets/locales/bg-BG/8.ogg
Normal file
Binary file not shown.
BIN
main/assets/locales/bg-BG/9.ogg
Normal file
BIN
main/assets/locales/bg-BG/9.ogg
Normal file
Binary file not shown.
BIN
main/assets/locales/bg-BG/activation.ogg
Normal file
BIN
main/assets/locales/bg-BG/activation.ogg
Normal file
Binary file not shown.
BIN
main/assets/locales/bg-BG/err_pin.ogg
Normal file
BIN
main/assets/locales/bg-BG/err_pin.ogg
Normal file
Binary file not shown.
BIN
main/assets/locales/bg-BG/err_reg.ogg
Normal file
BIN
main/assets/locales/bg-BG/err_reg.ogg
Normal file
Binary file not shown.
59
main/assets/locales/bg-BG/language.json
Normal file
59
main/assets/locales/bg-BG/language.json
Normal file
@@ -0,0 +1,59 @@
|
||||
{
|
||||
"language": {
|
||||
"type": "bg-BG"
|
||||
},
|
||||
"strings": {
|
||||
"WARNING": "Предупреждение",
|
||||
"INFO": "Информация",
|
||||
"ERROR": "Грешка",
|
||||
"VERSION": "Версия ",
|
||||
"LOADING_PROTOCOL": "Влизане в системата...",
|
||||
"INITIALIZING": "Инициализация...",
|
||||
"PIN_ERROR": "Моля, поставете SIM карта",
|
||||
"REG_ERROR": "Не може да се осъществи достъп до мрежата, моля проверете статуса на SIM картата",
|
||||
"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": "Свързване...",
|
||||
"CONNECTION_SUCCESSFUL": "Успешно свързване",
|
||||
"CONNECTED_TO": "Свързан към ",
|
||||
"LISTENING": "Слушане...",
|
||||
"SPEAKING": "Говорене...",
|
||||
"SERVER_NOT_FOUND": "Търсене на налична услуга",
|
||||
"SERVER_NOT_CONNECTED": "Не може да се свърже с услугата, моля опитайте по-късно",
|
||||
"SERVER_TIMEOUT": "Времето за изчакване на отговор изтече",
|
||||
"SERVER_ERROR": "Неуспешно изпращане, моля проверете мрежата",
|
||||
"CONNECT_TO_HOTSPOT": "Горещa точка: ",
|
||||
"ACCESS_VIA_BROWSER": " Конфигурационен URL: ",
|
||||
"WIFI_CONFIG_MODE": "Режим на конфигуриране на Wi-Fi",
|
||||
"ENTERING_WIFI_CONFIG_MODE": "Влизане в режим на конфигуриране на Wi-Fi...",
|
||||
"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 включен",
|
||||
"PLEASE_WAIT": "Моля, изчакайте...",
|
||||
"FOUND_NEW_ASSETS": "Намерени нови ресурси: %s",
|
||||
"DOWNLOAD_ASSETS_FAILED": "Неуспешно изтегляне на ресурси",
|
||||
"LOADING_ASSETS": "Зареждане на ресурси...",
|
||||
"HELLO_MY_FRIEND": "Здравей, мой приятел!",
|
||||
"FLIGHT_MODE_OFF": "Режим на самолет е изключен",
|
||||
"FLIGHT_MODE_ON": "Режим на самолет е включен",
|
||||
"MODEM_INIT_ERROR": "Неуспешна инициализация на модема"
|
||||
}
|
||||
}
|
||||
BIN
main/assets/locales/bg-BG/upgrade.ogg
Normal file
BIN
main/assets/locales/bg-BG/upgrade.ogg
Normal file
Binary file not shown.
BIN
main/assets/locales/bg-BG/welcome.ogg
Normal file
BIN
main/assets/locales/bg-BG/welcome.ogg
Normal file
Binary file not shown.
BIN
main/assets/locales/bg-BG/wificonfig.ogg
Normal file
BIN
main/assets/locales/bg-BG/wificonfig.ogg
Normal file
Binary file not shown.
BIN
main/assets/locales/ca-ES/0.ogg
Normal file
BIN
main/assets/locales/ca-ES/0.ogg
Normal file
Binary file not shown.
BIN
main/assets/locales/ca-ES/1.ogg
Normal file
BIN
main/assets/locales/ca-ES/1.ogg
Normal file
Binary file not shown.
BIN
main/assets/locales/ca-ES/2.ogg
Normal file
BIN
main/assets/locales/ca-ES/2.ogg
Normal file
Binary file not shown.
BIN
main/assets/locales/ca-ES/3.ogg
Normal file
BIN
main/assets/locales/ca-ES/3.ogg
Normal file
Binary file not shown.
BIN
main/assets/locales/ca-ES/4.ogg
Normal file
BIN
main/assets/locales/ca-ES/4.ogg
Normal file
Binary file not shown.
BIN
main/assets/locales/ca-ES/5.ogg
Normal file
BIN
main/assets/locales/ca-ES/5.ogg
Normal file
Binary file not shown.
BIN
main/assets/locales/ca-ES/6.ogg
Normal file
BIN
main/assets/locales/ca-ES/6.ogg
Normal file
Binary file not shown.
BIN
main/assets/locales/ca-ES/7.ogg
Normal file
BIN
main/assets/locales/ca-ES/7.ogg
Normal file
Binary file not shown.
BIN
main/assets/locales/ca-ES/8.ogg
Normal file
BIN
main/assets/locales/ca-ES/8.ogg
Normal file
Binary file not shown.
BIN
main/assets/locales/ca-ES/9.ogg
Normal file
BIN
main/assets/locales/ca-ES/9.ogg
Normal file
Binary file not shown.
BIN
main/assets/locales/ca-ES/activation.ogg
Normal file
BIN
main/assets/locales/ca-ES/activation.ogg
Normal file
Binary file not shown.
BIN
main/assets/locales/ca-ES/err_pin.ogg
Normal file
BIN
main/assets/locales/ca-ES/err_pin.ogg
Normal file
Binary file not shown.
BIN
main/assets/locales/ca-ES/err_reg.ogg
Normal file
BIN
main/assets/locales/ca-ES/err_reg.ogg
Normal file
Binary file not shown.
59
main/assets/locales/ca-ES/language.json
Normal file
59
main/assets/locales/ca-ES/language.json
Normal file
@@ -0,0 +1,59 @@
|
||||
{
|
||||
"language": {
|
||||
"type": "ca-ES"
|
||||
},
|
||||
"strings": {
|
||||
"WARNING": "Advertència",
|
||||
"INFO": "Informació",
|
||||
"ERROR": "Error",
|
||||
"VERSION": "Versió ",
|
||||
"LOADING_PROTOCOL": "Iniciant sessió...",
|
||||
"INITIALIZING": "Inicialitzant...",
|
||||
"PIN_ERROR": "Si us plau, inseriu la targeta SIM",
|
||||
"REG_ERROR": "No es pot accedir a la xarxa, si us plau comproveu l'estat de la targeta SIM",
|
||||
"DETECTING_MODULE": "Detectant mòdul...",
|
||||
"REGISTERING_NETWORK": "Esperant la xarxa...",
|
||||
"CHECKING_NEW_VERSION": "Comprovant nova versió...",
|
||||
"CHECK_NEW_VERSION_FAILED": "La comprovació de nova versió ha fallat, es tornarà a intentar en %d segons: %s",
|
||||
"SWITCH_TO_WIFI_NETWORK": "Canviant a Wi-Fi...",
|
||||
"SWITCH_TO_4G_NETWORK": "Canviant a 4G...",
|
||||
"STANDBY": "En espera",
|
||||
"CONNECT_TO": "Connectar a ",
|
||||
"CONNECTING": "Connectant...",
|
||||
"CONNECTION_SUCCESSFUL": "Connexió exitosa",
|
||||
"CONNECTED_TO": "Connectat a ",
|
||||
"LISTENING": "Escoltant...",
|
||||
"SPEAKING": "Parlant...",
|
||||
"SERVER_NOT_FOUND": "Buscant servei disponible",
|
||||
"SERVER_NOT_CONNECTED": "No es pot connectar al servei, si us plau intenteu-ho més tard",
|
||||
"SERVER_TIMEOUT": "Temps d'espera de resposta exhaurit",
|
||||
"SERVER_ERROR": "L'enviament ha fallat, si us plau comproveu la xarxa",
|
||||
"CONNECT_TO_HOTSPOT": "Punt d'accés: ",
|
||||
"ACCESS_VIA_BROWSER": " URL de configuració: ",
|
||||
"WIFI_CONFIG_MODE": "Mode de configuració Wi-Fi",
|
||||
"ENTERING_WIFI_CONFIG_MODE": "Entrant en mode de configuració Wi-Fi...",
|
||||
"SCANNING_WIFI": "Escanejant Wi-Fi...",
|
||||
"NEW_VERSION": "Nova versió ",
|
||||
"OTA_UPGRADE": "Actualització OTA",
|
||||
"UPGRADING": "El sistema s'està actualitzant...",
|
||||
"UPGRADE_FAILED": "L'actualització ha fallat",
|
||||
"ACTIVATION": "Activació",
|
||||
"BATTERY_LOW": "Bateria baixa",
|
||||
"BATTERY_CHARGING": "Carregant",
|
||||
"BATTERY_FULL": "Bateria plena",
|
||||
"BATTERY_NEED_CHARGE": "Bateria baixa, si us plau carregueu",
|
||||
"VOLUME": "Volum ",
|
||||
"MUTED": "Silenciat",
|
||||
"MAX_VOLUME": "Volum màxim",
|
||||
"RTC_MODE_OFF": "AEC desactivat",
|
||||
"RTC_MODE_ON": "AEC activat",
|
||||
"PLEASE_WAIT": "Si us plau, espereu...",
|
||||
"FOUND_NEW_ASSETS": "S'han trobat nous recursos: %s",
|
||||
"DOWNLOAD_ASSETS_FAILED": "No s'han pogut descarregar els recursos",
|
||||
"LOADING_ASSETS": "Carregant recursos...",
|
||||
"HELLO_MY_FRIEND": "Hola, amic meu!",
|
||||
"FLIGHT_MODE_OFF": "El mode avió està desactivat",
|
||||
"FLIGHT_MODE_ON": "El mode avió està activat",
|
||||
"MODEM_INIT_ERROR": "Error d'inicialització del mòdem"
|
||||
}
|
||||
}
|
||||
BIN
main/assets/locales/ca-ES/upgrade.ogg
Normal file
BIN
main/assets/locales/ca-ES/upgrade.ogg
Normal file
Binary file not shown.
BIN
main/assets/locales/ca-ES/welcome.ogg
Normal file
BIN
main/assets/locales/ca-ES/welcome.ogg
Normal file
Binary file not shown.
BIN
main/assets/locales/ca-ES/wificonfig.ogg
Normal file
BIN
main/assets/locales/ca-ES/wificonfig.ogg
Normal file
Binary file not shown.
@@ -1,58 +1,59 @@
|
||||
{
|
||||
"language": {
|
||||
"type" :"cs-CZ"
|
||||
"type": "cs-CZ"
|
||||
},
|
||||
"strings": {
|
||||
"WARNING":"Varování",
|
||||
"INFO":"Informace",
|
||||
"ERROR":"Chyba",
|
||||
"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...",
|
||||
|
||||
"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"
|
||||
"OTA_UPGRADE": "OTA upgrade",
|
||||
"UPGRADING": "Aktualizace systému...",
|
||||
"UPGRADE_FAILED": "Upgrade selhal",
|
||||
"ACTIVATION": "Aktivace zařízení",
|
||||
"BATTERY_LOW": "Slabá baterie",
|
||||
"BATTERY_CHARGING": "Nabíjení",
|
||||
"BATTERY_FULL": "Baterie plná",
|
||||
"BATTERY_NEED_CHARGE": "Slabá baterie, prosím nabijte",
|
||||
"VOLUME": "Hlasitost ",
|
||||
"MUTED": "Ztlumeno",
|
||||
"MAX_VOLUME": "Maximální hlasitost",
|
||||
"RTC_MODE_OFF": "AEC vypnuto",
|
||||
"RTC_MODE_ON": "AEC zapnuto",
|
||||
"DOWNLOAD_ASSETS_FAILED": "Nepodařilo se stáhnout prostředky",
|
||||
"LOADING_ASSETS": "Načítání prostředků...",
|
||||
"PLEASE_WAIT": "Prosím čekejte...",
|
||||
"FOUND_NEW_ASSETS": "Nalezeny nové prostředky: %s",
|
||||
"HELLO_MY_FRIEND": "Ahoj, můj příteli!",
|
||||
"CONNECTION_SUCCESSFUL": "Připojení úspěšné",
|
||||
"FLIGHT_MODE_OFF": "Letecký režim je vypnutý",
|
||||
"FLIGHT_MODE_ON": "Letecký režim je zapnutý",
|
||||
"MODEM_INIT_ERROR": "Chyba inicializace modemu"
|
||||
}
|
||||
}
|
||||
}
|
||||
BIN
main/assets/locales/da-DK/0.ogg
Normal file
BIN
main/assets/locales/da-DK/0.ogg
Normal file
Binary file not shown.
BIN
main/assets/locales/da-DK/1.ogg
Normal file
BIN
main/assets/locales/da-DK/1.ogg
Normal file
Binary file not shown.
BIN
main/assets/locales/da-DK/2.ogg
Normal file
BIN
main/assets/locales/da-DK/2.ogg
Normal file
Binary file not shown.
BIN
main/assets/locales/da-DK/3.ogg
Normal file
BIN
main/assets/locales/da-DK/3.ogg
Normal file
Binary file not shown.
BIN
main/assets/locales/da-DK/4.ogg
Normal file
BIN
main/assets/locales/da-DK/4.ogg
Normal file
Binary file not shown.
BIN
main/assets/locales/da-DK/5.ogg
Normal file
BIN
main/assets/locales/da-DK/5.ogg
Normal file
Binary file not shown.
BIN
main/assets/locales/da-DK/6.ogg
Normal file
BIN
main/assets/locales/da-DK/6.ogg
Normal file
Binary file not shown.
BIN
main/assets/locales/da-DK/7.ogg
Normal file
BIN
main/assets/locales/da-DK/7.ogg
Normal file
Binary file not shown.
BIN
main/assets/locales/da-DK/8.ogg
Normal file
BIN
main/assets/locales/da-DK/8.ogg
Normal file
Binary file not shown.
BIN
main/assets/locales/da-DK/9.ogg
Normal file
BIN
main/assets/locales/da-DK/9.ogg
Normal file
Binary file not shown.
BIN
main/assets/locales/da-DK/activation.ogg
Normal file
BIN
main/assets/locales/da-DK/activation.ogg
Normal file
Binary file not shown.
BIN
main/assets/locales/da-DK/err_pin.ogg
Normal file
BIN
main/assets/locales/da-DK/err_pin.ogg
Normal file
Binary file not shown.
BIN
main/assets/locales/da-DK/err_reg.ogg
Normal file
BIN
main/assets/locales/da-DK/err_reg.ogg
Normal file
Binary file not shown.
59
main/assets/locales/da-DK/language.json
Normal file
59
main/assets/locales/da-DK/language.json
Normal file
@@ -0,0 +1,59 @@
|
||||
{
|
||||
"language": {
|
||||
"type": "da-DK"
|
||||
},
|
||||
"strings": {
|
||||
"WARNING": "Advarsel",
|
||||
"INFO": "Information",
|
||||
"ERROR": "Fejl",
|
||||
"VERSION": "Version ",
|
||||
"LOADING_PROTOCOL": "Logger ind...",
|
||||
"INITIALIZING": "Initialiserer...",
|
||||
"PIN_ERROR": "Indsæt venligst SIM-kort",
|
||||
"REG_ERROR": "Kan ikke få adgang til netværket, tjek venligst SIM-kortets status",
|
||||
"DETECTING_MODULE": "Detekterer modul...",
|
||||
"REGISTERING_NETWORK": "Venter på netværk...",
|
||||
"CHECKING_NEW_VERSION": "Tjekker for ny version...",
|
||||
"CHECK_NEW_VERSION_FAILED": "Tjek for ny version mislykkedes, prøver igen om %d sekunder: %s",
|
||||
"SWITCH_TO_WIFI_NETWORK": "Skifter til Wi-Fi...",
|
||||
"SWITCH_TO_4G_NETWORK": "Skifter til 4G...",
|
||||
"STANDBY": "Standby",
|
||||
"CONNECT_TO": "Forbind til ",
|
||||
"CONNECTING": "Forbinder...",
|
||||
"CONNECTION_SUCCESSFUL": "Forbindelse lykkedes",
|
||||
"CONNECTED_TO": "Forbundet til ",
|
||||
"LISTENING": "Lytter...",
|
||||
"SPEAKING": "Taler...",
|
||||
"SERVER_NOT_FOUND": "Søger efter tilgængelig tjeneste",
|
||||
"SERVER_NOT_CONNECTED": "Kan ikke forbinde til tjeneste, prøv venligst igen senere",
|
||||
"SERVER_TIMEOUT": "Timeout ved venten på svar",
|
||||
"SERVER_ERROR": "Afsendelse mislykkedes, tjek venligst netværket",
|
||||
"CONNECT_TO_HOTSPOT": "Hotspot: ",
|
||||
"ACCESS_VIA_BROWSER": " Konfigurations-URL: ",
|
||||
"WIFI_CONFIG_MODE": "Wi-Fi-konfigurationstilstand",
|
||||
"ENTERING_WIFI_CONFIG_MODE": "Går ind i Wi-Fi-konfigurationstilstand...",
|
||||
"SCANNING_WIFI": "Scanner Wi-Fi...",
|
||||
"NEW_VERSION": "Ny version ",
|
||||
"OTA_UPGRADE": "OTA-opgradering",
|
||||
"UPGRADING": "Systemet opgraderes...",
|
||||
"UPGRADE_FAILED": "Opgradering mislykkedes",
|
||||
"ACTIVATION": "Aktivering",
|
||||
"BATTERY_LOW": "Lavt batteri",
|
||||
"BATTERY_CHARGING": "Oplader",
|
||||
"BATTERY_FULL": "Batteriet er fuldt",
|
||||
"BATTERY_NEED_CHARGE": "Lavt batteri, oplad venligst",
|
||||
"VOLUME": "Lydstyrke ",
|
||||
"MUTED": "Lydløs",
|
||||
"MAX_VOLUME": "Maksimal lydstyrke",
|
||||
"RTC_MODE_OFF": "AEC slukket",
|
||||
"RTC_MODE_ON": "AEC tændt",
|
||||
"PLEASE_WAIT": "Vent venligst...",
|
||||
"FOUND_NEW_ASSETS": "Fandt nye ressourcer: %s",
|
||||
"DOWNLOAD_ASSETS_FAILED": "Download af ressourcer mislykkedes",
|
||||
"LOADING_ASSETS": "Indlæser ressourcer...",
|
||||
"HELLO_MY_FRIEND": "Hej, min ven!",
|
||||
"FLIGHT_MODE_OFF": "Flytilstand er slukket",
|
||||
"FLIGHT_MODE_ON": "Flytilstand er tændt",
|
||||
"MODEM_INIT_ERROR": "Modeminitialisering mislykkedes"
|
||||
}
|
||||
}
|
||||
BIN
main/assets/locales/da-DK/upgrade.ogg
Normal file
BIN
main/assets/locales/da-DK/upgrade.ogg
Normal file
Binary file not shown.
BIN
main/assets/locales/da-DK/welcome.ogg
Normal file
BIN
main/assets/locales/da-DK/welcome.ogg
Normal file
Binary file not shown.
BIN
main/assets/locales/da-DK/wificonfig.ogg
Normal file
BIN
main/assets/locales/da-DK/wificonfig.ogg
Normal file
Binary file not shown.
@@ -1,58 +1,59 @@
|
||||
{
|
||||
"language": {
|
||||
"type" :"de-DE"
|
||||
"type": "de-DE"
|
||||
},
|
||||
"strings": {
|
||||
"WARNING":"Warnung",
|
||||
"INFO":"Information",
|
||||
"ERROR":"Fehler",
|
||||
"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...",
|
||||
|
||||
"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"
|
||||
"OTA_UPGRADE": "OTA-Upgrade",
|
||||
"UPGRADING": "System wird aktualisiert...",
|
||||
"UPGRADE_FAILED": "Upgrade fehlgeschlagen",
|
||||
"ACTIVATION": "Gerät aktivieren",
|
||||
"BATTERY_LOW": "Niedriger Batteriestand",
|
||||
"BATTERY_CHARGING": "Wird geladen",
|
||||
"BATTERY_FULL": "Batterie voll",
|
||||
"BATTERY_NEED_CHARGE": "Niedriger Batteriestand, bitte aufladen",
|
||||
"VOLUME": "Lautstärke ",
|
||||
"MUTED": "Stummgeschaltet",
|
||||
"MAX_VOLUME": "Maximale Lautstärke",
|
||||
"RTC_MODE_OFF": "AEC aus",
|
||||
"RTC_MODE_ON": "AEC ein",
|
||||
"DOWNLOAD_ASSETS_FAILED": "Fehler beim Herunterladen der Ressourcen",
|
||||
"LOADING_ASSETS": "Ressourcen werden geladen...",
|
||||
"PLEASE_WAIT": "Bitte warten...",
|
||||
"FOUND_NEW_ASSETS": "Neue Ressourcen gefunden: %s",
|
||||
"HELLO_MY_FRIEND": "Hallo, mein Freund!",
|
||||
"CONNECTION_SUCCESSFUL": "Verbindung erfolgreich",
|
||||
"FLIGHT_MODE_OFF": "Flugmodus ist deaktiviert",
|
||||
"FLIGHT_MODE_ON": "Flugmodus ist aktiviert",
|
||||
"MODEM_INIT_ERROR": "Modem-Initialisierung fehlgeschlagen"
|
||||
}
|
||||
}
|
||||
}
|
||||
BIN
main/assets/locales/el-GR/0.ogg
Normal file
BIN
main/assets/locales/el-GR/0.ogg
Normal file
Binary file not shown.
BIN
main/assets/locales/el-GR/1.ogg
Normal file
BIN
main/assets/locales/el-GR/1.ogg
Normal file
Binary file not shown.
BIN
main/assets/locales/el-GR/2.ogg
Normal file
BIN
main/assets/locales/el-GR/2.ogg
Normal file
Binary file not shown.
BIN
main/assets/locales/el-GR/3.ogg
Normal file
BIN
main/assets/locales/el-GR/3.ogg
Normal file
Binary file not shown.
BIN
main/assets/locales/el-GR/4.ogg
Normal file
BIN
main/assets/locales/el-GR/4.ogg
Normal file
Binary file not shown.
BIN
main/assets/locales/el-GR/5.ogg
Normal file
BIN
main/assets/locales/el-GR/5.ogg
Normal file
Binary file not shown.
BIN
main/assets/locales/el-GR/6.ogg
Normal file
BIN
main/assets/locales/el-GR/6.ogg
Normal file
Binary file not shown.
BIN
main/assets/locales/el-GR/7.ogg
Normal file
BIN
main/assets/locales/el-GR/7.ogg
Normal file
Binary file not shown.
BIN
main/assets/locales/el-GR/8.ogg
Normal file
BIN
main/assets/locales/el-GR/8.ogg
Normal file
Binary file not shown.
BIN
main/assets/locales/el-GR/9.ogg
Normal file
BIN
main/assets/locales/el-GR/9.ogg
Normal file
Binary file not shown.
BIN
main/assets/locales/el-GR/activation.ogg
Normal file
BIN
main/assets/locales/el-GR/activation.ogg
Normal file
Binary file not shown.
BIN
main/assets/locales/el-GR/err_pin.ogg
Normal file
BIN
main/assets/locales/el-GR/err_pin.ogg
Normal file
Binary file not shown.
BIN
main/assets/locales/el-GR/err_reg.ogg
Normal file
BIN
main/assets/locales/el-GR/err_reg.ogg
Normal file
Binary file not shown.
59
main/assets/locales/el-GR/language.json
Normal file
59
main/assets/locales/el-GR/language.json
Normal file
@@ -0,0 +1,59 @@
|
||||
{
|
||||
"language": {
|
||||
"type": "el-GR"
|
||||
},
|
||||
"strings": {
|
||||
"WARNING": "Προειδοποίηση",
|
||||
"INFO": "Πληροφορίες",
|
||||
"ERROR": "Σφάλμα",
|
||||
"VERSION": "Έκδοση ",
|
||||
"LOADING_PROTOCOL": "Σύνδεση...",
|
||||
"INITIALIZING": "Αρχικοποίηση...",
|
||||
"PIN_ERROR": "Παρακαλώ εισαγάγετε κάρτα SIM",
|
||||
"REG_ERROR": "Αδυναμία πρόσβασης στο δίκτυο, ελέγξτε την κατάσταση της κάρτας SIM",
|
||||
"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": "Σύνδεση...",
|
||||
"CONNECTION_SUCCESSFUL": "Επιτυχής σύνδεση",
|
||||
"CONNECTED_TO": "Συνδέθηκε σε ",
|
||||
"LISTENING": "Ακρόαση...",
|
||||
"SPEAKING": "Ομιλία...",
|
||||
"SERVER_NOT_FOUND": "Αναζήτηση διαθέσιμης υπηρεσίας",
|
||||
"SERVER_NOT_CONNECTED": "Αδυναμία σύνδεσης στην υπηρεσία, παρακαλώ δοκιμάστε αργότερα",
|
||||
"SERVER_TIMEOUT": "Λήξη χρόνου αναμονής απόκρισης",
|
||||
"SERVER_ERROR": "Η αποστολή απέτυχε, ελέγξτε το δίκτυο",
|
||||
"CONNECT_TO_HOTSPOT": "Σημείο πρόσβασης: ",
|
||||
"ACCESS_VIA_BROWSER": " URL διαμόρφωσης: ",
|
||||
"WIFI_CONFIG_MODE": "Λειτουργία διαμόρφωσης Wi-Fi",
|
||||
"ENTERING_WIFI_CONFIG_MODE": "Είσοδος σε λειτουργία διαμόρφωσης Wi-Fi...",
|
||||
"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 ενεργοποιημένο",
|
||||
"PLEASE_WAIT": "Παρακαλώ περιμένετε...",
|
||||
"FOUND_NEW_ASSETS": "Βρέθηκαν νέοι πόροι: %s",
|
||||
"DOWNLOAD_ASSETS_FAILED": "Αποτυχία λήψης πόρων",
|
||||
"LOADING_ASSETS": "Φόρτωση πόρων...",
|
||||
"HELLO_MY_FRIEND": "Γεια σου, φίλε μου!",
|
||||
"FLIGHT_MODE_OFF": "Η λειτουργία πτήσης είναι απενεργοποιημένη",
|
||||
"FLIGHT_MODE_ON": "Η λειτουργία πτήσης είναι ενεργή",
|
||||
"MODEM_INIT_ERROR": "Αποτυχία αρχικοποίησης modem"
|
||||
}
|
||||
}
|
||||
BIN
main/assets/locales/el-GR/upgrade.ogg
Normal file
BIN
main/assets/locales/el-GR/upgrade.ogg
Normal file
Binary file not shown.
BIN
main/assets/locales/el-GR/welcome.ogg
Normal file
BIN
main/assets/locales/el-GR/welcome.ogg
Normal file
Binary file not shown.
BIN
main/assets/locales/el-GR/wificonfig.ogg
Normal file
BIN
main/assets/locales/el-GR/wificonfig.ogg
Normal file
Binary file not shown.
@@ -11,49 +11,49 @@
|
||||
"INITIALIZING": "Initializing...",
|
||||
"PIN_ERROR": "Please insert SIM card",
|
||||
"REG_ERROR": "Unable to access network, please check SIM card status",
|
||||
"MODEM_INIT_ERROR": "Modem initialization failed",
|
||||
"DETECTING_MODULE": "Detecting module...",
|
||||
"FLIGHT_MODE_ON": "Flight mode is on",
|
||||
"FLIGHT_MODE_OFF": "Flight mode is off",
|
||||
"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"
|
||||
"RTC_MODE_ON": "AEC On",
|
||||
"PLEASE_WAIT": "Please wait...",
|
||||
"FOUND_NEW_ASSETS": "Found new assets: %s",
|
||||
"DOWNLOAD_ASSETS_FAILED": "Failed to download assets",
|
||||
"LOADING_ASSETS": "Loading assets...",
|
||||
"HELLO_MY_FRIEND": "Hello, my friend!"
|
||||
}
|
||||
}
|
||||
@@ -1,58 +1,59 @@
|
||||
{
|
||||
"language": {
|
||||
"type" :"es-ES"
|
||||
"type": "es-ES"
|
||||
},
|
||||
"strings": {
|
||||
"WARNING":"Advertencia",
|
||||
"INFO":"Información",
|
||||
"ERROR":"Error",
|
||||
"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...",
|
||||
|
||||
"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"
|
||||
"OTA_UPGRADE": "Actualización OTA",
|
||||
"UPGRADING": "Actualizando sistema...",
|
||||
"UPGRADE_FAILED": "Actualización fallida",
|
||||
"ACTIVATION": "Activación del dispositivo",
|
||||
"BATTERY_LOW": "Batería baja",
|
||||
"BATTERY_CHARGING": "Cargando",
|
||||
"BATTERY_FULL": "Batería llena",
|
||||
"BATTERY_NEED_CHARGE": "Batería baja, por favor cargar",
|
||||
"VOLUME": "Volumen ",
|
||||
"MUTED": "Silenciado",
|
||||
"MAX_VOLUME": "Volumen máximo",
|
||||
"RTC_MODE_OFF": "AEC desactivado",
|
||||
"RTC_MODE_ON": "AEC activado",
|
||||
"DOWNLOAD_ASSETS_FAILED": "Error al descargar recursos",
|
||||
"LOADING_ASSETS": "Cargando recursos...",
|
||||
"PLEASE_WAIT": "Por favor espere...",
|
||||
"FOUND_NEW_ASSETS": "Encontrados nuevos recursos: %s",
|
||||
"HELLO_MY_FRIEND": "¡Hola, mi amigo!",
|
||||
"CONNECTION_SUCCESSFUL": "Conexión exitosa",
|
||||
"FLIGHT_MODE_OFF": "El modo avión está desactivado",
|
||||
"FLIGHT_MODE_ON": "El modo avión está activado",
|
||||
"MODEM_INIT_ERROR": "Error de inicialización del módem"
|
||||
}
|
||||
}
|
||||
}
|
||||
BIN
main/assets/locales/fa-IR/0.ogg
Normal file
BIN
main/assets/locales/fa-IR/0.ogg
Normal file
Binary file not shown.
BIN
main/assets/locales/fa-IR/1.ogg
Normal file
BIN
main/assets/locales/fa-IR/1.ogg
Normal file
Binary file not shown.
BIN
main/assets/locales/fa-IR/2.ogg
Normal file
BIN
main/assets/locales/fa-IR/2.ogg
Normal file
Binary file not shown.
BIN
main/assets/locales/fa-IR/3.ogg
Normal file
BIN
main/assets/locales/fa-IR/3.ogg
Normal file
Binary file not shown.
BIN
main/assets/locales/fa-IR/4.ogg
Normal file
BIN
main/assets/locales/fa-IR/4.ogg
Normal file
Binary file not shown.
BIN
main/assets/locales/fa-IR/5.ogg
Normal file
BIN
main/assets/locales/fa-IR/5.ogg
Normal file
Binary file not shown.
BIN
main/assets/locales/fa-IR/6.ogg
Normal file
BIN
main/assets/locales/fa-IR/6.ogg
Normal file
Binary file not shown.
BIN
main/assets/locales/fa-IR/7.ogg
Normal file
BIN
main/assets/locales/fa-IR/7.ogg
Normal file
Binary file not shown.
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user