899 Commits

Author SHA1 Message Date
417f52d759 perf(websocket): switch WiFi to performance mode before connecting (#1985)
Some checks failed
Build Boards / Determine variants to build (push) Has been cancelled
Build Boards / Build ${{ matrix.full_name }} (push) Has been cancelled
* perf(websocket): switch WiFi to performance mode before connecting

Optimize WebSocket connection speed by switching WiFi to performance
mode before establishing the connection, instead of after.

This reduces network latency significantly:
- TCP connection: 1093ms → 88ms (92% faster)
- WebSocket handshake: 1035ms → 80ms (92% faster)
- Total network layer: 2128ms → 173ms (92% faster)

The issue was caused by WiFi power save mode (MAX_MODEM) which adds
significant latency to packet transmission.

* Adjust formatting
2026-05-14 14:36:14 +08:00
67bf599149 fix(otto): WebSocket direct clients not receiving MCP responses (#1992)
* Enhance Otto Robot camera support by adding configuration for OV3660. Updated config.h to define camera types and GPIO settings, modified config.json to include new camera options, and refactored otto_robot.cc for improved camera detection and initialization logic.

* fix: 移除 OttoEmojiDisplay 构造函数中的 SetTheme 调用以修复 LoadProhibited 崩溃

Made-with: Cursor

* refactor: improve audio service error handling and codec timeout management

- Updated AudioService to prevent input task termination on read timeout, introducing a delay instead.
- Enhanced NoAudioCodec to implement a read timeout for I2S channel reads.
- Adjusted WebSocketControlServer to set a control port for improved socket management.
- Added manufacturer information to the config.json for waveshare ESP32-Touch-LCD-3.5.

* fix(otto): WebSocket direct clients not receiving MCP responses

When a browser connects directly to the WebSocket control server (port
8080) and sends a JSON-RPC request, the MCP response was routed through
Application::SendMcpMessage -> protocol_->SendMcpMessage, which sends it
to the cloud protocol channel. As a result, the direct WebSocket client
never received the response, while the WeChat mini-program could because
it communicates via the cloud.

Fix:
- Add BroadcastMessage() to WebSocketControlServer, using
  httpd_queue_work + httpd_ws_send_frame_async to asynchronously
  send responses back to all connected clients on port 8080
- Add RegisterMcpBroadcastCallback() to Application, allowing an
  additional MCP send callback to be registered; SendMcpMessage()
  now invokes it alongside the cloud protocol
- Register the broadcast callback in OttoRobot after the WebSocket
  server starts successfully

Also add WebSocket direct-connect API documentation to README.md
with complete JSON-RPC 2.0 command examples.
2026-05-14 14:35:49 +08:00
ba27c12494 fix(no_audio_codec): replace kReadTimeoutTicks with kReadTimeoutMs for clarity and consistency 2026-05-07 22:11:42 +08:00
c1d520d700 Feat: Add battery support and small fixes for Freenove 2.8 board (#1976)
* feat(freenove-esp32s3): add battery level retrieval

* fix(freenove-esp32s3): add missing comma in config.json

* docs(freenove-esp32s3): note possible shared design with ES3C28P/ES3N28P
2026-05-07 20:51:58 +08:00
1847b58935 fix(mcp): remove unnecessary guard for self.assets.set_download_url tool registration
The guard around the registration of the self.assets.set_download_url tool has been removed, ensuring it is always available for configuration. This change addresses issues on 32MB flash devices where the tool was previously skipped due to partition validation checks.

Fixes #1962
2026-05-02 15:56:47 +08:00
2be3c2cb1a fix(mcp): always register self.assets.set_download_url tool for 32MB flash devices (#1971)
* fix(m5stack-tab5): remove stale esp_video==0.7.0 dependency instructions

The README previously instructed users to override esp_video to 0.7.0
and esp_ipa to 0.1.0, but this causes build failures because:
- esp_video 0.7.0 does not export esp_video_deinit(), resulting in
  linker errors ('MAP_FAILED' and 'esp_video_deinit' not declared)
- The project's main/idf_component.yml already pins the correct
  version (esp_video==1.3.1) that the source code expects

Users should now use the default dependency versions from idf_component.yml
without modification.

Fixes #1957

* fix(mcp): always register self.assets.set_download_url tool

On 32MB flash devices the assets partition layout differs from the
default, causing partition_valid() to return false and silently
skipping registration of the self.assets.set_download_url MCP tool.
Users see 'Unknown tool: self.assets.set_download_url' from their MCP
client.

The tool writes to Settings storage which works regardless of the
partition map, so the partition_valid() guard is unnecessary.
Move the AddUserOnlyTool call outside the guard so the tool is always
available for explicit configuration via MCP.

Fixes #1962

---------

Co-authored-by: Aayush Pratap Singh <aayushpratap.singh@gmail.com>
2026-05-02 06:23:25 +08:00
e12e7351d9 Merge pull request #1958 from rymcu/main
feat(board): add rymcu-bigsmart board support
2026-04-30 17:16:40 +08:00
20175fa059 Move RYMCU BigSmart under manufacturer directory
Create main/boards/rymcu/bigsmart so future RYMCU boards can live under the same manufacturer directory. Update CMake to set MANUFACTURER to rymcu while preserving BOARD_NAME as rymcu-bigsmart, and adjust config.json so release output remains rymcu-bigsmart.
2026-04-30 16:04:30 +08:00
8cbbf3f357 chore: update dependencies in idf_component.yml
- Bump esp-wifi-connect version from ~3.1.2 to ~3.1.3
- Update uart-eth-modem version from ~0.3.4 to ~0.4.0
2026-04-30 13:29:36 +08:00
79a482a09e fix(blufi): GET_WIFI_LIST triggers real-time scan with guaranteed response (#1964)
* fix(blufi): GET_WIFI_LIST triggers real-time scan with guaranteed response

Previously, ESP_BLUFI_EVENT_GET_WIFI_LIST waited for any in-progress scan
to finish and then returned the cached result. When the cache was empty
(e.g. after a config-mode transition that stopped the Wi-Fi driver),
_send_wifi_list() returned silently with no response frame, leaving the
App waiting until timeout.

Changes:
- GET_WIFI_LIST now clears the cache and starts a fresh scan immediately.
- _wifi_scan_event_handler calls _send_wifi_list() after every scan
  triggered by a GET_WIFI_LIST request.
- start_wifi_scan() calls esp_wifi_start() before esp_wifi_scan_start()
  to handle the case where the driver was stopped during a mode
  transition (ESP_ERR_WIFI_STATE is treated as already-started).
- _send_wifi_list() sends ESP_BLUFI_WIFI_SCAN_FAIL when no APs are
  found, so the App always receives a terminal response.
- Redundant static_cast in _wifi_scan_event_handler replaced with the
  existing local `self` pointer.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* fix(blufi): preserve cache fast-path, fall back to live scan only when needed

Address review feedback on always-rescan latency regression.

The GET_WIFI_LIST handler now distinguishes three cases:

1. Scan in flight: defer the response via m_send_list_after_scan; the
   scan-done handler dispatches when it fires. Removes the previous
   blocking `while (m_scan_in_progress) vTaskDelay(500)` which would
   stall the BluFi event task indefinitely if the scan never completed.

2. Cache populated: respond from cache immediately (~50 ms, no latency
   change vs original behavior). _send_wifi_list() still kicks off an
   async refresh scan as before to keep the cache fresh.

3. Cache empty and no scan running: trigger a live scan and dispatch
   from the scan-done handler. If start_wifi_scan() fails, send
   ESP_BLUFI_WIFI_SCAN_FAIL so the App exits its wait state.

State variables are also disentangled:

- m_scan_should_save_ssid keeps its original meaning (write scan results
  into m_ap_records). Cleared during connect-to-AP so the connect-time
  scan does not pollute the cache.
- m_send_list_after_scan is new and tracks "the next scan-done event
  should respond to a pending GET_WIFI_LIST request". The previous PR
  conflated these two responsibilities onto m_scan_should_save_ssid,
  which would have caused init-time scans to spuriously emit a wifi list
  to the App.

start_wifi_scan() now returns bool so the caller can distinguish
"scan started or already running" from "could not start a scan".

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

---------

Co-authored-by: Yixin Shi <shiyixin@qiniu.com>
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-30 09:27:49 +08:00
73ad50c732 feat: add M5Stack AtomS3R Echo Pyramid board (#1959)
Made-with: Cursor
2026-04-28 13:55:39 +08:00
07e2a11253 feat(board): add rymcu-bigsmart board support 2026-04-23 20:44:35 +08:00
8865950405 Merge pull request #1949 from Cosmic183123/main
content:add-waveshare-esp32-s3-touch-amoled-2.16
2026-04-21 16:37:33 +08:00
b72945a78a content:fix-ESP32-S3-Touch-AMOLED-2.16-readme.md 2026-04-21 14:41:09 +08:00
cde254cdf0 Merge pull request #1943 from zqyhimself/fix/waveshare-p4-7b-config
fix(waveshare-p4-7b): target v1.x chip rev and 32MB flash layout
2026-04-21 14:41:01 +08:00
b7dc88f6ab fix(esp32-p4): split each P4 build into rev<3 + -p4x twin variants
【中文】
针对 PR #1943 的评审建议(Y1hsiaochunnn + laride):当前市面的 ESP32-P4
几乎都是 rev v1.x / v2.x 硅片,IDF 默认 REV_MIN_301 会让 bootloader 被
bootloader.rev3.ld 链到高位 HP_SRAM,导致在存量硬件上第一条指令就 panic。
未来 ESP32-P4X(rev >= 3.x)又需要保留默认配置,因此不能在所有 P4 board
上一刀切地写死 CONFIG_ESP32P4_SELECTS_REV_LESS_V3=y。

方案:对所有 P4 config.json 的每个现有变体,添加 REV_LESS_V3 + REV_MIN_100,
并复制一份加 `-p4x` 后缀的孪生变体(不加上述两行,保持 IDF 默认 REV_MIN_301
以支持未来 P4X 芯片)。

受影响的 6 份 config.json,共 14 个原变体,复制后新增 14 个 `-p4x` 变体:
- main/boards/waveshare/esp32-p4-wifi6-touch-lcd/config.json(8 -> 16 变体,
  其中 7b 变体保留 32MB flash + custom 分区配置)
- main/boards/waveshare/esp32-p4-wifi6-touch-lcd-3.5/config.json
- main/boards/waveshare/esp32-p4-nano/config.json
- main/boards/esp-p4-function-ev-board/config.json
- main/boards/wireless-tag-wtp4c5mp07s/config.json
- main/boards/m5stack-tab5/config.json

---

[English]
Per review on PR #1943 (Y1hsiaochunnn + laride): almost all ESP32-P4 silicon
on the market today is rev v1.x / v2.x. IDF's default REV_MIN_301 links the
bootloader via bootloader.rev3.ld into the upper HP_SRAM window, which those
chips cannot execute; the CPU panics on the first opcode. Future ESP32-P4X
(rev >= 3.x) still needs the IDF default, so we cannot hard-code
CONFIG_ESP32P4_SELECTS_REV_LESS_V3=y across all P4 boards.

Strategy: for each existing variant in every P4 config.json, add REV_LESS_V3
+ REV_MIN_100 to target current silicon, and add a `-p4x` twin variant
without those two configs (keeping IDF default REV_MIN_301) for future P4X
chips.

Affects 6 config.json files, 14 original variants duplicated into 14 `-p4x`
twins:
- main/boards/waveshare/esp32-p4-wifi6-touch-lcd/config.json (8 -> 16
  variants; the 7b variant keeps its 32 MB flash + custom partition configs)
- main/boards/waveshare/esp32-p4-wifi6-touch-lcd-3.5/config.json
- main/boards/waveshare/esp32-p4-nano/config.json
- main/boards/esp-p4-function-ev-board/config.json
- main/boards/wireless-tag-wtp4c5mp07s/config.json
- main/boards/m5stack-tab5/config.json
2026-04-21 14:30:58 +08:00
f78c59a954 content:add-waveshare-esp32-s3-touch-amoled-2.16 2026-04-21 09:52:20 +08:00
49ac8a6da3 chore: upgrade version to 2.2.6 (#1944)
Agent-Logs-Url: https://github.com/78/xiaozhi-esp32/sessions/d669edcb-2b68-4b41-81d6-b542a11b92e9

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: 78 <4488133+78@users.noreply.github.com>
2026-04-18 02:12:02 +08:00
2461efdc72 fix(waveshare-p4-7b): target v1.x chip rev and 32MB flash layout
【中文】
7B 变体使用 v1.x 版本的 ESP32-P4 芯片和 32MB flash,但 config.json 中
对应的 sdkconfig_append 既没声明芯片版本,也没声明 flash 大小。IDF 因此
默认按 rev v3.1 + 16MB flash 构建,bootloader 被链接脚本
bootloader.rev3.ld 放到 0x4ffa_xxxx 的高位 HP_SRAM,这个区域在 v1.x
硅上不可取指,ROM 加载完跳过去,CPU 在第一条指令就
"Guru Meditation Error: Core 0 panic'ed (Illegal instruction)",
bootloader log 一行都打不出来。

添加 CONFIG_ESP32P4_SELECTS_REV_LESS_V3=y + CONFIG_ESP32P4_REV_MIN_100=y
让 bootloader.ld(低位 HP_SRAM 0x4ff2_xxxx)被选中,并声明
CONFIG_ESPTOOLPY_FLASHSIZE_32MB=y + partitions/v2/32m.csv,使 image
header 和分区表和板子实际硬件对齐;CONFIG_ESPTOOLPY_FLASH_MODE_AUTO_DETECT=n
与已知 32MB 板子 sensecap-watcher 保持一致。

在 v1.3 版本的 P4-WIFI6-Touch-LCD-7B 上验证通过:bootloader 段现在加载到
0x4ff33ce0 / 0x4ff29ed0 / 0x4ff2cbd0;启动过程中 MIPI-DSI LCD、GT911
触控、OV5647 摄像头、ES8311+ES7210 音频和 ESP32-C6 SDIO 协处理器
全部正常初始化;状态机进入 wifi_configuring,对外发出 Xiaozhi-XXXX 配网热点。

---

[English]
The 7B variant ships with a v1.x ESP32-P4 silicon and a 32 MB flash, but
the existing sdkconfig_append declared neither. IDF then defaults to rev
v3.1 + 16 MB, and the bootloader is linked via bootloader.rev3.ld into
the 0x4ffa_xxxx upper HP_SRAM window. That range is not fetchable on
v1.x silicon, so the ROM jumps to the loaded bootloader and the CPU
panics on the first opcode with "Guru Meditation Error: Core 0 panic'ed
(Illegal instruction)" before any bootloader log is printed.

Add CONFIG_ESP32P4_SELECTS_REV_LESS_V3=y + CONFIG_ESP32P4_REV_MIN_100=y
so bootloader.ld (low HP_SRAM 0x4ff2_xxxx) is used, and declare
CONFIG_ESPTOOLPY_FLASHSIZE_32MB=y + partitions/v2/32m.csv so the image
header and partition offsets match the board. Disable flash-mode
auto-detect for parity with the other known 32 MB board (sensecap-watcher).

Verified on a v1.3 P4-WIFI6-Touch-LCD-7B: bootloader segments now load
at 0x4ff33ce0 / 0x4ff29ed0 / 0x4ff2cbd0; boot completes through MIPI DSI,
GT911 touch, OV5647 camera, ES8311+ES7210 audio and the ESP32-C6 SDIO
coprocessor; device reaches wifi_configuring and exposes the Xiaozhi-XXXX AP.
2026-04-18 01:38:06 +08:00
e5ebde454e Merge pull request #1937 from DrayxR3X/esp32-s3-touch-amoled-1.43c
add waveshare esp32-s3-touch-amoled-1.43c
2026-04-17 13:59:37 +08:00
d2687956cd resolve conflict 2026-04-17 10:48:13 +08:00
87f6faee79 Update Chinese and English documentation for custom board setup and MCP protocol
- Added a comprehensive guide for creating custom boards in the XiaoZhi AI project, detailing directory structure, configuration files, and initialization code.
- Introduced a new document explaining the MCP protocol for IoT control, including message formats and interaction flows.
- Updated existing documentation to reflect changes in tool registration and usage examples for the MCP protocol.
- Enhanced README files for better clarity and consistency across languages.
2026-04-17 03:36:37 +08:00
69b1a978e9 Add NULLLAB-AI-VOX3 Board (#1900) 2026-04-16 19:31:53 +08:00
6074fdeb71 feat(cardputer-adv): add TCA8418 keyboard and WiFi config UI (#1929)
Add full keyboard support and keyboard-based WiFi configuration for
M5Stack Cardputer Adv:

- TCA8418 I2C keyboard driver with 56-key matrix, interrupt-driven
  key events, and debounce handling
- Keyboard WiFi config UI: scan/select/input SSID and password
  directly on the device without needing a phone
- Volume control (up/down arrows) and brightness control (left/right)
  via keyboard with fine-step adjustment near bounds
- Enter key to toggle chat state
- Display offset and backlight fixes for ST7789V2
- README with flash parameters and hardware specs

Co-authored-by: bot <bot@localhost>
2026-04-14 17:02:00 +08:00
7dc61300d1 add waveshare esp32-s3-touch-amoled-1.43c 2026-04-14 15:52:40 +08:00
97c0e75eec feat:添加正点原子DNESP32S3B3开发板的小智AI例程 (#1931) 2026-04-13 21:09:11 +08:00
efeb3ad119 fix: remove submodule (#1925) 2026-04-10 17:09:39 +08:00
36d742e4d7 ESP-VoCat: BMI270 motion feedback, capacitive slider (v1.2), and single-pad button (v1.0) (#1902)
* Add support bmi270

* Add support slider

* Add support touch for v1.0
2026-04-08 10:12:56 +08:00
ab2cae5746 Fix crash when adjusting volume via button while Es8311 audio device is disabled (#1917)
* Initial plan

* Fix crash when adjusting volume via button while audio device is disabled

When both input and output are disabled, UpdateDeviceState() sets dev_ to
nullptr. Pressing a volume button calls SetOutputVolume() which previously
called esp_codec_dev_set_out_vol(dev_, volume) without null-checking dev_,
causing a crash via ESP_ERROR_CHECK.

Fix: Add null guard for dev_ and mutex lock for thread safety. The volume
is still saved via AudioCodec::SetOutputVolume() and will be applied when
the device is reopened by UpdateDeviceState().

Agent-Logs-Url: https://github.com/78/xiaozhi-esp32/sessions/945c653a-ed16-49af-aefe-5cfb473402c6

Co-authored-by: 78 <4488133+78@users.noreply.github.com>

---------

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: 78 <4488133+78@users.noreply.github.com>
2026-04-07 18:35:06 +08:00
7a7c74a747 Add touch screen support to freenove 2.8 (#1901)
* Add touch screen support to freenove 2.8

Volume and brightness levels on vertical/horizontal swipe
Listening, chat state and wifi config on press/long press

* Simplified

Removed swipes. Touch quiet unresponsive on Freenove board.

* Remove unused parts

* Modify long tap duration in TouchTask

Updated touch driver logic to change long tap duration from 600ms to 3000ms.

* Cosmetic fix
2026-04-07 17:18:24 +08:00
cc7cbe78ba Merge pull request #1821 from ggc121238/main
feat: add waveshare esp32-s3-cam-xxxx support
2026-04-03 14:14:35 +08:00
ggc
314edc5c51 content: add ESP32-S3-CAM-OVxxxx 2026-04-02 16:37:24 +08:00
7e7890183e Content: fixed ESP_LCD_TOUCH_IO_I2C_FT5x06_CONFIG issue 2026-04-02 14:21:01 +08:00
2c5d7757e5 Content: Removed some irrelevant code 2026-04-02 14:21:01 +08:00
43b4d35b2e Content: Removed irrelevant code 2026-04-02 14:21:01 +08:00
33ed917172 content: fixed config.json and config.h 2026-04-02 14:21:01 +08:00
89d51fdc23 content: add ESP32-P4-WIFI6-Touch-LCD-3.5 2026-04-02 14:21:01 +08:00
022d9848de Add freenove-esp32s3-display-2.8-lcd (#1876)
* add freenove-esp32s3-display-2.8-lcd

from https://github.com/Freenove/xiaozhi-esp32 and updated to v2.2.4

* add Freenove_ESP32S3_DISPLAY_2_8_LCD to configs

* Update from manufacturer

https://github.com/Freenove/xiaozhi-esp32/tree/New

* Delete main/boards/freenove-esp32s3-display-2.8-lcd/_static/ReadMe/media-kit-2.8-lcd-top.jpg

orphan

* Delete main/boards/freenove-esp32s3-display-2.8-lcd/_static/ReadMe/media-kit-2.8-lcd-sideview.jpg

orphan

* Delete main/boards/freenove-esp32s3-display-2.8-lcd/_static/ReadMe directory

* readme update
2026-04-01 12:46:53 +08:00
8afebe560a Merge pull request #1895 from Y1hsiaochunnn/touchcompatible
fix: Default configuration of GT911
2026-03-31 10:22:59 +08:00
a63f8bc08b fix: Default configuration of GT911 2026-03-31 10:10:12 +08:00
4dc1a8c75f Merge pull request #1892 from DrayxR3X/esp32-c6-touch-amoled-2.16
add waveshare esp32-c6-touch-amoled-2.16
2026-03-31 09:16:16 +08:00
121a2d45e7 Merge branch '78:main' into esp32-c6-touch-amoled-2.16 2026-03-30 18:16:11 +08:00
06b3b7613c Merge pull request #1891 from Y1hsiaochunnn/gt911_err
fix: Compilation errors caused by default configuration changes of the touch chip
2026-03-30 16:17:58 +08:00
addf5fcc64 fix: touch configuration security risk fixed 2026-03-30 15:29:31 +08:00
a877d95f74 fix: touch_config errors 2026-03-30 15:12:22 +08:00
76a5c19000 add waveshare esp32-c6-touch-amoled-2.16 2026-03-30 15:07:45 +08:00
7d63797dfa fix: GT911 config errors 2026-03-30 15:05:20 +08:00
0f3199a812 feat: adapt to esp_codec_dev>=1.5.5 (#1878)
* feat: adapt to esp_codec_dev>=1.5.5

* fix: fix board config resolution in release script
2026-03-26 23:56:45 +08:00
6d51b9dbde Bump version to 2.2.5 (#1882)
* Initial plan

* bump version to 2.2.5

Co-authored-by: 78 <4488133+78@users.noreply.github.com>
Agent-Logs-Url: https://github.com/78/xiaozhi-esp32/sessions/841b9fce-b34b-4cbd-b46a-20b48fd35d4c

---------

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: 78 <4488133+78@users.noreply.github.com>
2026-03-26 23:52:38 +08:00
d340efe58d Remove unused flag for playing popup sound on listening state in ContinueWakeWordInvoke() function (#1881) 2026-03-26 13:12:02 +08:00