diff --git a/CHANGELOG.md b/CHANGELOG.md index 9f83de3..bedc809 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,12 +7,11 @@ Versioning and Conventional Commits. ### Added -- Per-board hardware, input, configuration, build and flashing instructions for all thirteen - profiles, with a linked board documentation index. +- Per-board hardware, input and operation documentation for all thirteen profiles, with shared + build/flash instructions and one validation matrix. - CoreS3-only process-gray pixel-glasses UI, with 23 expressions, four 9 px terminal rows, a 10 px signature and fixed 32 px six-digit pairing codes on its 320x240 display. - Automatic faces follow READY/conversation phases; four MCP emotions use bounded holds, - replacement and same-name new-command replay. Expressions affect only the LCD. + Automatic faces follow READY/conversation phases. Expressions affect only the LCD. `MYBOT_BOARD` selects the view automatically; other twelve profiles retain their UI/hardware. - Shared LVGL status UI for the other display-board profiles, with Chinese/English text, pairing codes, voiceprint status, and listening/thinking/speaking indicators. @@ -47,8 +46,7 @@ Versioning and Conventional Commits. CST816S touch input, and ES7210/ES8311 full-duplex audio. - Pinned ST77916 2.0.2 and CST816S 1.1.1~1 production components. - Pinned CO5300 2.1.0, LCD touch 1.2.1, and CST9217 1.0.4 production components. -- agent-studio-device-firmware SDK 1.2.0 plus post-release fixes, Agora RTSA 1.10.1 and - reference-counted AOSL integration. +- agent-studio-device-firmware 1.2.0 plus post-release fixes, Agora RTSA 1.10.1 and reference-counted AOSL integration. - Wi-Fi provisioning/reconnect, NVS, verified HTTPS, I2S audio, buttons and LVGL status UI. - Persistent 0-100 speaker volume using the Zhengchen board's software I2S gain path. - Embedded Chinese and English Ogg/Opus pairing-code announcements decoded to PSRAM at runtime. @@ -71,27 +69,28 @@ Versioning and Conventional Commits. AIC3104 output initialization, XIAO Boot input, and XVF onboard-button polling. - SenseCAP Watcher Board profile with ES8311/ES7243E audio, SPD2010 status display, rotary input, TCA9555 power sequencing, and a factory-data-preserving 32 MB partition layout. -- Target firmware CI with 30 configurations: all thirteen board profiles in both languages, - CoreS3 video in both languages, and light-theme/static-indicator variants, using 60 ms audio. +- Target firmware CI for all board profiles in both languages, CoreS3 video and UI variants, + using 60 ms audio. Current status is tracked in the [validation matrix](docs/VALIDATION.md). ### Changed -- Refresh the Chinese and English Wi-Fi provisioning prompts while preserving 20 ms mono Opus/Ogg. - -- Refresh the 22 Chinese and English pairing prompt and digit recordings. Preserve the 20 ms - mono Opus/Ogg format. - -Historical SDK commit IDs below refer to the -[agent-studio-device-firmware history](https://github.com/AgoraIO-Community/agent-studio-device-firmware/commits/main/). - -- Use agent-studio-device-firmware v1.3.0 (`32ac74b`) and report version 1.3.0 from +- Centralize build and flash commands in the board index and current validation status in + `docs/VALIDATION.md`; remove repeated status paragraphs, volatile build timings and per-board + command copies from board and topic documentation. +- Refresh the SDK snapshot to `baf41ba` and register the new shared URL and HTTP-header sources. + Adopt bounded URL validation and printable header checks, remove unused outbound RTM, media-mute + and LCD emotion paths, and update the CoreS3 adapter and host tests to the current LCD contract. +- Update the local Chinese and English Wi-Fi provisioning prompts, retaining 20 ms mono Opus/Ogg + and recording checksums and decoded frame counts. +- Refresh the SDK snapshot to `3f9a1ad` (version 1.3.0) and update all 22 Chinese/English pairing + prompt and digit recordings from its PCM assets. Encode 20 ms mono Opus/Ogg for the existing + firmware decoder and record source/output hashes. +- Sync the SDK snapshot to the v1.3.0 release (`58f0ef9`) and report version 1.3.0 from the ESP-IDF wrapper. Changes since the previous snapshot are release metadata and comments. -- Document the pinned SDK, announcement assets and delivered platform implementations with - reproducible checksums and retained third-party notices. -- Use agent-studio-device-firmware SDK `d158022` (1.2.0 plus post-release fixes), accepting cloud +- Sync the SDK snapshot to `39d5ed1` (1.2.0 plus post-release fixes), accepting cloud `message.user` envelopes with absolute and relative volume commands. Remove MCP mute, expression, and bare-command parsing upstream; retain the platform's LCD emotion rendering. -- Replace only the CoreS3 status-card renderer with the BK7259 pixel-glasses display implementation, +- Replace only the CoreS3 status-card renderer with the BK7259 `dc4c854` display implementation, adapted to the existing ESP32 adapter/API. READY uses NEUTRAL; conversation entry uses SURPRISED for 300 ms plus its 250 ms enabled transition, continuous thinking becomes PROCESSING after three seconds, and MCP holds are 2/3/1.2/0.8 seconds plus transition. @@ -99,17 +98,17 @@ Historical SDK commit IDs below refer to the Existing touch, audio, video auto-selection, power, memory and immutable SDK inputs are retained. - Update the language-derived device-service addresses to `https://botstation.shengwang.cn/api` for zh-CN and `https://botstation.agora.io/api` for en-US, matching the SDK's regional guidance. -- Use agent-studio-device-firmware SDK `e7793eb` (1.2.0 plus post-release fixes), - adding cloud volume/mute commands and moving status polls and stop notifications off the control worker. +- Sync the SDK snapshot to `e7793eb` (1.2.0 plus post-release fixes), adding cloud + volume/mute commands and moving status polls and stop notifications off the control worker. Register the new device-command source in ESP-IDF. The shared workflow view on other boards continues to ignore optional emotion indicators; CoreS3 maps them to pixel expressions. -- Sync the agent-studio-device-firmware SDK snapshot to `0643978` (1.2.0 plus post-release fixes), preventing control +- Sync the SDK snapshot to `0643978` (1.2.0 plus post-release fixes), preventing control queue stalls, clearing pending starts on re-pairing, discarding stale announcement PCM, and hardening HTTP and JSON boundaries. The RTC queue limit increases from 64 to 1000 pending calls. - Direct pairing-code entry to the web console and scroll the instruction on narrow displays. - Select the device API region from the firmware language: zh-CN uses Shanghai (sh2), and en-US uses Singapore (sg3). -- Sync the agent-studio-device-firmware SDK snapshot to `83fbcb0` (1.2.0 plus post-release fixes), serializing video +- Sync the SDK snapshot to `83fbcb0` (1.2.0 plus post-release fixes), serializing video control with shutdown, retaining announcements until RTC callbacks stop, and consolidating RTM-to-LCD indicator handling and device-service response parsing. - Request CoreS3 DVP capture at most five times per second, holding capture buffers between @@ -119,9 +118,9 @@ Historical SDK commit IDs below refer to the - Count in-flight SPI callbacks across consecutive CoreS3 LVGL UI flushes so teardown waits for all pending transfers. -- Refresh the agent-studio-device-firmware SDK to commit `4ae239c` (1.2.0 plus post-release fixes): set - AOSL to NOTICE at SDK startup, reduce routine RTM logging, and preserve the log level across RTSA initialization. -- Group the agent-studio-device-firmware SDK, AOSL, and Agora RTSA under `components/mybot_stack`, retaining independent +- Refresh the SDK to commit `4ae239c` (1.2.0 plus post-release fixes): set AOSL to NOTICE + at SDK startup, reduce routine RTM logging, and preserve the log level across RTSA initialization. +- Group agent-studio-device-firmware, AOSL, and Agora RTSA under `components/mybot_stack`, retaining independent ESP-IDF component names and registering them explicitly through `EXTRA_COMPONENT_DIRS`. - Organize the platform as board profiles, platform registration, services, drivers, internal headers, and assets. Separate display panel lifecycle, LVGL adapters, and the shared view. @@ -129,11 +128,11 @@ Historical SDK commit IDs below refer to the AtomEchoS3R and ReSpeaker Flex remain headless; theme and activity-animation settings remain configurable. - Set the ESP32 FreeRTOS tick rate to 1000 Hz so one operating-system tick is 1 ms. -- Sync the vendored agent-studio-device-firmware SDK to Unreleased commit `27324e7`, adding RTM channel subscription for +- Sync the vendored SDK to Unreleased commit `27324e7`, adding RTM channel subscription for voice-print status. -- Sync the vendored agent-studio-device-firmware SDK to v1.1.0 + Unreleased commit `e515f07`, including the serialized RTC +- Sync the vendored SDK to v1.1.0 + Unreleased commit `e515f07`, including the serialized RTC MPQ implementation, pairing-state projection, media-session cleanup, and bounded service parsing. -- Sync the vendored agent-studio-device-firmware SDK to v1.2.0 (`674dcbf`), adding optional multimodal video uplink and +- Sync the vendored SDK to v1.2.0 (`674dcbf`), adding optional multimodal video uplink and mutually exclusive server-state LCD indicators while keeping video disabled on ESP32-S3 boards. - Enforce the bundled ESP32-S3 RTSA package's fixed 60 ms cadence at component configuration time; non-60 ms packet durations now require a matching RTSA package. @@ -141,16 +140,16 @@ Historical SDK commit IDs below refer to the adaptations. - Align the bilingual project, contribution, support, porting, and release documentation with the standalone ESP32 firmware scope. -- Decouple network provisioning from agent-studio-device-firmware startup. Connectivity is now a - prerequisite, and holding Boot stops the SDK before provisioning, shows the Wi-Fi setup screen, - and restarts the SDK after the station obtains an IP address. +- Decouple network provisioning from SDK startup. Connectivity is now a prerequisite, and holding + Boot stops the SDK before provisioning, shows the Wi-Fi setup screen, and restarts the SDK after the + station obtains an IP address. - Select the target Board at compile time and separate common platform services, reusable drivers, and the Zhengchen board profile without changing its runtime behavior. - Share the Zhengchen Board lifecycle between the ML307 and Wi-Fi profiles while keeping their compile-time hardware configuration isolated. - Log volume-up and volume-down button presses in the ESP32-S3 platform layer. - Shorten the provisioning AP SSID to `mybot-aabb`, using the first two STA MAC bytes. -- Sync the vendored agent-studio-device-firmware SDK to the v1.0.0 release (`117a44d`), retaining the ESP32-S3 RTC and +- Sync the vendored SDK to the v1.0.0 release (`117a44d`), retaining the ESP32-S3 RTC and HTTPS-only compatibility patches. ### Removed @@ -161,40 +160,8 @@ Historical SDK commit IDs below refer to the ### Known limitations -- CoreS3 LVGL, including the theme/emoji stage, has passed real-device testing. The subsequent - rollout and renderer cleanup across display boards, and the latest provisioning SSID/scrolling - changes, still need hardware regression testing. The newer 5 fps DVP sampling and larger DMA - buffers also require CPU, internal-memory, and concurrent-audio measurements. Conversation transcripts, cloud emotion - messages, and GIF animation are not included. -- ML307/4G and wake words are not yet supported. -- Zhengchen Wi-Fi real-device validation, physical PSRAM-capacity confirmation, 16 kHz playback - validation, charge/battery inputs, temperature monitoring, and power management are not yet - complete. -- Xingzhi Cube real-device validation, physical Flash/PSRAM-capacity confirmation, 16 kHz - playback, display/power/button checks, battery/charging inputs, shutdown, sleep, and low-power - behavior are not yet complete. -- Bread Compact Wi-Fi LCD real-device validation is pending. Its fixed - N16R8/ST7789/separate-I2S wiring, 16 kHz playback, panel/backlight/input, and detected capacities - require verification. Camera, touch, volume buttons, LED, lamp, and power management are unsupported. -- ESP-VoCat real-device validation for both PCB revisions is not yet complete. Battery reporting, - IMU, PCB capacitive controls, SD card, LED, camera expansion, local AEC, reference audio, - shutdown, and low-power behavior are not supported by the initial profile. -- Waveshare AMOLED 1.75 and 1.75C real-device validation, playback-reference input, local AEC, - battery reporting, and low-power operation are not yet complete. The 1.75C profile does not - support RTC, IMU, TF card, or TCA9554 and conservatively addresses 16 MB of Flash pending - real-device capacity confirmation. -- Waveshare AMOLED 2.16 real-device power/audio/display/touch testing, physical Flash/PSRAM - capacities, and optional TCA9554 presence remain unconfirmed. Video, playback-reference input, - local AEC, RTC, IMU, TF card, battery reporting, shutdown, and low-power behavior are unsupported. -- ReSpeaker Flex requires separately flashed XVF3800 Circular-4 16 kHz I2S firmware; hardware - validation, Linear-4 support, XVF firmware update, LED-ring status, and LCD output are not yet - complete. -- SenseCAP Watcher real-device validation, camera, touch, LED, battery reporting, shutdown, and - low-power behavior are not yet complete. -- M5Stack StickS3 real-device validation, GPIO12, IMU, infrared, battery reporting, shutdown, and - low-power behavior are not yet complete. -- M5Stack AtomEchoS3R real-device validation, GPIO41 user-button mapping, and 16 kHz bidirectional - audio testing are not yet complete. +Current build coverage, real-device results and unsupported features are tracked only in the +[validation matrix](docs/VALIDATION.md). ### Fixed @@ -219,7 +186,7 @@ Historical SDK commit IDs below refer to the pipe. - Preserve the requested AOSL thread stack size on ESP-IDF instead of dividing the byte count by `sizeof(StackType_t)`. -- Increase the lwIP socket budget so agent-studio-device-firmware and Agora can open network sockets after AOSL creates +- Increase the lwIP socket budget so mybot and Agora can open network sockets after AOSL creates its MPQ wakeup pipes. - Make ESP32-S3 AOSL millisecond sleeps block for at least one FreeRTOS tick so MPQ teardown cannot starve the task that releases its final queue reference. diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index fb7236f..8f9d108 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -32,10 +32,10 @@ git diff --check ``` Use a separate build directory and sdkconfig for each board or configuration variant. The -[CI workflow](.github/workflows/ci.yml) defines 30 firmware builds: thirteen boards in both languages, -two additional CoreS3 video builds, one CoreS3 light-theme build, and one CoreS3 video build with -conversation animations disabled. All use the bundled RTSA package's 60 ms audio frames; 20 ms -and 40 ms configurations are rejected until a matching RTSA package is supplied. +[CI workflow](.github/workflows/ci.yml) builds every profile in both languages and adds the +CoreS3 video and UI variants. All use the bundled RTSA package's 60 ms audio frames; 20 ms and +40 ms configurations are rejected until a matching RTSA package is supplied. Current validation +status is tracked only in the [validation matrix](docs/VALIDATION.md). LVGL is the only renderer on display boards; AtomEchoS3R and ReSpeaker Flex are headless. Do not add an opt-in LVGL preset or a legacy-renderer fallback. See [board porting](docs/BOARD_PORTING.md) and diff --git a/CONTRIBUTING.zh-CN.md b/CONTRIBUTING.zh-CN.md index 3e939ad..d83131a 100644 --- a/CONTRIBUTING.zh-CN.md +++ b/CONTRIBUTING.zh-CN.md @@ -30,9 +30,9 @@ git diff --check ``` 每个板型或配置变体使用独立构建目录和 sdkconfig。[CI 工作流](.github/workflows/ci.yml) -定义了 30 项固件构建:十三个板型分别构建中英文版本,另加 CoreS3 两种语言的视频构建、 -一个浅色主题构建,以及一个关闭会话动画的视频构建。全部使用随附 RTSA 支持的 60 ms -音频帧;在提供匹配的 RTSA 包之前,20 ms 和 40 ms 配置会被拒绝。 +构建全部板型的中英文版本,并包含 CoreS3 视频与 UI 变体。全部使用随附 RTSA 支持的 +60 ms 音频帧;在提供匹配的 RTSA 包之前,20 ms 和 40 ms 配置会被拒绝。当前验证状态统一 +记录在[验证矩阵](docs/VALIDATION.md)中。 所有带屏板型只使用 LVGL,AtomEchoS3R 与 ReSpeaker Flex 保持无屏;不要新增启用 LVGL 的可选 preset 或旧 渲染器回退。职责边界见[板级移植](docs/BOARD_PORTING.zh-CN.md)和 diff --git a/README.md b/README.md index 8b6b42a..0de49e5 100644 --- a/README.md +++ b/README.md @@ -117,20 +117,14 @@ CPU, heap, and playback diagnostics can be enabled with ## Validation -The [CI workflow](.github/workflows/ci.yml) defines 30 ESP-IDF v5.5.2 firmware builds: both -languages for all thirteen profiles, two additional CoreS3 video builds, one CoreS3 light-theme -build, and one CoreS3 video build with conversation animations disabled. Host tests cover the -board lifecycles and CoreS3 pixel UI. - -CI builds and host tests do not establish panel behavior, power sequencing, audio quality, Wi-Fi -recovery, or other real-device results. Earlier CoreS3 audio and camera paths passed hardware -tests; the current pixel-glasses UI and shared LVGL changes still require hardware regression. -Validation status and unsupported features for every profile are recorded in its board README. -Bread Compact Wi-Fi LCD, Xingzhi Cube, and AMOLED 2.16 currently have build validation only. +Build coverage, recorded real-device results and unsupported areas are maintained in one +[validation matrix](docs/VALIDATION.md). CI builds and host tests do not establish panel behavior, +power sequencing, audio quality, Wi-Fi recovery or other real-device results. ## Documentation - [Board profiles](components/mybot_platform/boards/README.md) +- [Validation matrix](docs/VALIDATION.md) - [Board porting](docs/BOARD_PORTING.md) - [Buffered audio playback](docs/AUDIO_PLAYBACK.md) - [Platform LVGL UI](docs/PLATFORM_UI.md) diff --git a/README.zh-CN.md b/README.zh-CN.md index 6f71282..aea4bc9 100644 --- a/README.zh-CN.md +++ b/README.zh-CN.md @@ -107,18 +107,14 @@ NVS 中没有 Wi-Fi 凭据时,设备创建名为 `mybot-xxxx` 的配置 AP, ## 验证 -[CI 工作流](.github/workflows/ci.yml)定义 30 项 ESP-IDF v5.5.2 固件构建:13 个板型分别 -构建中英文版本,另有两种语言的 CoreS3 视频构建、一个浅色主题构建,以及一个关闭会话动画 -的视频构建。宿主测试覆盖板级生命周期和 CoreS3 像素 UI。 - -CI 构建和宿主测试不能证明屏幕行为、上电时序、音频质量、Wi-Fi 恢复等真机结果。此前 -CoreS3 音频和摄像头通路已完成真机测试;当前像素眼镜 UI 与共享 LVGL 改动仍需真机回归。 -各 profile 的验证状态和未支持能力记录在对应板卡说明中。Bread Compact Wi-Fi LCD、行者 -Cube 和 AMOLED 2.16 当前只有构建验证。 +构建覆盖、已记录的真机结果和未支持能力统一维护在 +[验证矩阵](docs/VALIDATION.md)中。CI 构建和宿主测试不能证明屏幕行为、上电时序、音频质量、 +Wi-Fi 恢复等真机结果。 ## 文档 - [板卡说明](components/mybot_platform/boards/README.md) +- [验证矩阵](docs/VALIDATION.md) - [板级移植](docs/BOARD_PORTING.zh-CN.md) - [音频播放缓冲](docs/AUDIO_PLAYBACK.zh-CN.md) - [平台 LVGL UI](docs/PLATFORM_UI.zh-CN.md) diff --git a/SUPPORT.md b/SUPPORT.md index 063402f..2bd7806 100644 --- a/SUPPORT.md +++ b/SUPPORT.md @@ -19,20 +19,14 @@ or only in a host-side UI test. Every display board uses LVGL automatically; the backend to select. AtomEchoS3R and ReSpeaker Flex have no display. For provisioning issues, describe whether they occur on first boot, after a long press, or when reconnecting with saved credentials. -The supported firmware network path is Wi-Fi on the Zhengchen 1.54 TFT ML307 and Wi-Fi profiles, -Xingzhi Cube 1.54 TFT Wi-Fi, Bread Compact Wi-Fi LCD, ESP-VoCat, -Waveshare ESP32-S3 Touch AMOLED 1.75, 1.75C, and 2.16, -M5Stack CoreS3, M5Stack StickS3, M5Stack AtomEchoS3R, ReSpeaker Flex XVF3800 Circular-4 with -XIAO ESP32S3, and SenseCAP Watcher. The -[CI workflow](.github/workflows/ci.yml) covers all thirteen profiles in both languages, with additional -CoreS3 video and UI variants. Build coverage does not establish real-device validation for a -particular firmware revision or hardware batch. ESP-VoCat reports must identify PCB V1.0 or V1.2 -and include the runtime detection log. -The three AMOLED profiles must match the physical board and must not be cross-flashed. ML307/4G +Supported profiles and hardware prerequisites are listed in the +[board index](components/mybot_platform/boards/README.md). Current build and hardware status is +tracked only in the [validation matrix](docs/VALIDATION.md). + +ESP-VoCat reports must identify PCB V1.0 or V1.2 and include the runtime detection log. The three +AMOLED profiles must match the physical board and must not be cross-flashed. Bread Compact Wi-Fi +LCD reports must identify the N16R8 module, ST7789 240x320 variant and actual wiring. ML307/4G reports are feature requests until a compatible network path is implemented and validated. -Bread Compact Wi-Fi LCD reports must identify the N16R8 module, ST7789 240x320 variant, and -actual wiring; other panel/I2S choices are outside this fixed profile. Chinese and English build -support has been validated; real-device testing remains pending. The bundled RTSA package supports 60 ms audio frames. A build rejected after selecting 20 ms or 40 ms requires a matching RTSA package, not a change to the board driver. diff --git a/SUPPORT.zh-CN.md b/SUPPORT.zh-CN.md index 6433b44..063c447 100644 --- a/SUPPORT.zh-CN.md +++ b/SUPPORT.zh-CN.md @@ -18,16 +18,13 @@ 使用 LVGL,不存在可切换的旧 UI 后端;AtomEchoS3R 与 ReSpeaker Flex 没有显示屏。配网问题请注明发生在 首次启动、长按触发,还是使用已保存凭据重新连接时。 -当前支持征辰 1.54 TFT ML307 与 Wi-Fi profile、行者 Cube 1.54 TFT Wi-Fi、Bread Compact Wi-Fi LCD、ESP-VoCat、Waveshare ESP32-S3 Touch -AMOLED 1.75、1.75C 与 2.16 profile、M5Stack CoreS3、M5Stack StickS3、M5Stack AtomEchoS3R,以及搭配 XIAO ESP32S3 -的 ReSpeaker Flex XVF3800 Circular-4 和 SenseCAP Watcher 的 Wi-Fi 固件路径。 -[CI 工作流](.github/workflows/ci.yml)覆盖十三个 profile 的中英文构建,以及额外的 CoreS3 视频和 -UI 变体。构建覆盖不代表某个固件版本或硬件批次已经通过真机验证。ESP-VoCat 问题必须注明 -PCB V1.0 或 V1.2,并附带运行时探测日志。三个 AMOLED profile 必须 -使用匹配的 profile,禁止交叉烧录。在实现并验证兼容网络路径之前,ML307/4G 相关问题按特性 +支持的 profile 与硬件前提见[板卡说明索引](components/mybot_platform/boards/README.md)。 +当前构建与真机状态统一记录在[验证矩阵](docs/VALIDATION.md)中。 + +ESP-VoCat 问题必须注明 PCB V1.0 或 V1.2,并附带运行时探测日志。三个 AMOLED profile 必须 +使用匹配的 profile,禁止交叉烧录。Bread Compact Wi-Fi LCD 问题需注明 N16R8 模组、 +240x320 ST7789 版本和实际接线。在实现并验证兼容网络路径之前,ML307/4G 相关问题按特性 请求处理。 -Bread Compact Wi-Fi LCD 问题需注明 N16R8 模组、240x320 ST7789 版本和实际接线;其他 -面板或 I2S 选择不在此固定 profile 范围内。中英文构建支持已验证,真机测试仍未完成。 随附 RTSA 包支持 60 ms 音频帧。选择 20 ms 或 40 ms 导致配置被拒绝时,需要提供匹配的 RTSA 包,而不是修改板级驱动。 diff --git a/THIRD_PARTY_NOTICES.md b/THIRD_PARTY_NOTICES.md index f0af3fe..7a0725a 100644 --- a/THIRD_PARTY_NOTICES.md +++ b/THIRD_PARTY_NOTICES.md @@ -5,7 +5,7 @@ It does not replace third-party terms. This file is informational and is not leg | Component | Terms | Location | | --- | --- | --- | -| agent-studio-device-firmware SDK 1.3.0 (`32ac74b`) | Apache-2.0; bundled JSON parser portions MIT | `components/mybot_stack/mybot_sdk/mybot` | +| agent-studio-device-firmware SDK 1.3.0 (`46e265a`) | Apache-2.0; bundled JSON parser portions MIT | `components/mybot_stack/mybot_sdk/mybot` | | AOSL (`84e0860`) | Bundled license: Apache-2.0 text plus additional deployment restrictions | `components/mybot_stack/aosl` | | Agora RTSA Lite for ESP32-S3 1.10.1 (build 1270872) | Separate Agora distribution terms | `components/mybot_stack/agora_rtc` | | esp-wifi-connect 3.2.2 | MIT | `components/esp-wifi-connect` | @@ -79,7 +79,7 @@ Source Han Sans UI glyphs retain the SIL OFL 1.1 terms in ## Vendored SDK Notice The SDK's public headers and core sources are pinned to -[agent-studio-device-firmware commit `32ac74bc59cb72db70e9a68337753561b59b13d0`](https://github.com/AgoraIO-Community/agent-studio-device-firmware/tree/32ac74bc59cb72db70e9a68337753561b59b13d0). +[agent-studio-device-firmware commit `46e265a960fac48d93ae6755bdf694aeb09ab366`](https://github.com/AgoraIO-Community/agent-studio-device-firmware/tree/46e265a960fac48d93ae6755bdf694aeb09ab366). The exact trees and reproducible archive checksum are recorded in [VENDORED_SOURCES.md](VENDORED_SOURCES.md). diff --git a/VENDORED_SOURCES.md b/VENDORED_SOURCES.md index 462ddde..1c8c34b 100644 --- a/VENDORED_SOURCES.md +++ b/VENDORED_SOURCES.md @@ -5,7 +5,7 @@ redistribution terms are documented separately in [THIRD_PARTY_NOTICES.md](THIRD | Path | Source | Pinned revision | | --- | --- | --- | -| `components/mybot_stack/mybot_sdk/mybot` | [agent-studio-device-firmware](https://github.com/AgoraIO-Community/agent-studio-device-firmware/tree/32ac74bc59cb72db70e9a68337753561b59b13d0) | tag `v1.3.0`, commit `32ac74bc59cb72db70e9a68337753561b59b13d0` | +| `components/mybot_stack/mybot_sdk/mybot` | [agent-studio-device-firmware](https://github.com/AgoraIO-Community/agent-studio-device-firmware/tree/46e265a960fac48d93ae6755bdf694aeb09ab366) | v1.3.0, `main` commit `46e265a960fac48d93ae6755bdf694aeb09ab366` | | `components/mybot_stack/aosl` | `github.com/AgoraIO-Community/aosl` | v1.0.4 + post-release fixes, commit `84e086084ebcd0ae2455a0ce5721950c5fe2e656` | | `components/mybot_stack/agora_rtc` | Agora RTSA Lite package archive | v1.10.1, build 1270872 (`20260828_194128`) | | `components/esp-wifi-connect` | `github.com/78/esp-wifi-connect` | 3.2.2, commit `c24b97c194e6b4a1d7be0237b3c28980661cac1e` | @@ -35,10 +35,10 @@ redistribution terms are documented separately in [THIRD_PARTY_NOTICES.md](THIRD The SDK's public headers and core sources match the pinned official commit. ESP-IDF integration also supplies the generated `include/mybot/mybot_version.h`. The official Git tree IDs are -`9ee3a8bd4f85a9b211c68e2a4edcb466fb6580b2` for `include/` and -`c0032496b56ae8c40bdc5f7fe41847ca4e720153` for `src/`. In a checkout of the SDK repository, -`git archive 32ac74bc59cb72db70e9a68337753561b59b13d0 include src | sha256sum` produces -`6443be044e8210057b0291e53b8ea6dcb92664f54b78fd9c71ac2f10c34e292e`. +`f0f111a3b7790a650dac9cb29c93edc2c52a5086` for `include/` and +`a6b52ae939875a49f0d8b04b512358aa9edea849` for `src/`. In a checkout of the SDK repository, +`git archive 46e265a960fac48d93ae6755bdf694aeb09ab366 include src | sha256sum` produces +`6c6717a50fab6132443a9fe98216b32d9edfc95b11a5a18514f72394c59f873d`. ## Board reference documents diff --git a/components/mybot_platform/boards/atom-echos3r/README.md b/components/mybot_platform/boards/atom-echos3r/README.md index 67163c7..b7a459f 100644 --- a/components/mybot_platform/boards/atom-echos3r/README.md +++ b/components/mybot_platform/boards/atom-echos3r/README.md @@ -12,7 +12,7 @@ | 分区 | [partitions/v2/8m.csv](../../../../partitions/v2/8m.csv),双 OTA 分区 | | 控制台 | ESP-IDF 默认 UART0,板级配置未覆盖控制台类型 | | 音频 | ES8311 采集/播放,GPIO18 控制功放;SDK 使用 16 kHz 单声道 signed-16 PCM | -| 输入 | 当前代码映射 GPIO41 为低电平有效用户按键,映射与极性仍需真机确认 | +| 输入 | 当前代码映射 GPIO41 为低电平有效用户按键 | | 显示 | 无屏幕,不编译 LVGL | | 摄像头 | 当前 profile 未提供视频接口,不支持开启视频 | @@ -24,30 +24,4 @@ GPIO0 已用于 I2C 时钟,不作为配网按键。 无已保存的 Wi-Fi 信息时自动创建配置热点并播放对应语言的提示音,运行状态和配对码可通过 串口日志查看。音量逻辑值保存到 NVS,初始默认值为 70;ES8311 硬件音量按逻辑值的 60% 映射。 -## 构建与烧录 - -在仓库根目录使用 ESP-IDF v5.5.2: - -```sh -source /path/to/esp-idf/export.sh -python3 scripts/build_all.py --board atom-echos3r --language both -``` - -输出 `releases/atom-echos3r-zh-CN.bin` 和对应英文固件。 -构建脚本的清理行为见[板卡索引](../README.md)。 - -直接构建中文固件并烧录时,使用独立目录;将串口替换为本机设备: - -```sh -idf.py -B build/atom-echos3r \ - -DMYBOT_BOARD=atom-echos3r \ - -DSDKCONFIG=build/atom-echos3r/sdkconfig \ - -DSDKCONFIG_DEFAULTS="sdkconfig.defaults;ci/ptime60.defaults" build -idf.py -B build/atom-echos3r -p /dev/ttyUSB0 flash monitor -``` - -## 验证范围 - -GPIO41 按键映射、极性、16 kHz 采集及播放质量尚未通过本工程真机验收。 -构建成功不能代替这些测试。详见[平台移植文档](../../../../docs/BOARD_PORTING.zh-CN.md) -及[项目说明](../../../../README.zh-CN.md)。 +构建、烧录与验证状态见[板卡索引](../README.md)和[验证矩阵](../../../../docs/VALIDATION.md)。 diff --git a/components/mybot_platform/boards/bread-compact-wifi-lcd/README.md b/components/mybot_platform/boards/bread-compact-wifi-lcd/README.md index 40b53d3..6193f3b 100644 --- a/components/mybot_platform/boards/bread-compact-wifi-lcd/README.md +++ b/components/mybot_platform/boards/bread-compact-wifi-lcd/README.md @@ -47,26 +47,4 @@ SDK 音频边界为 16 kHz、单声道、signed-16 PCM;物理标准 I2S 使用 连接该热点后访问 `http://192.168.4.1` 配置 Wi-Fi。进入配网时播放对应语言提示音,取得 可用 IP 后才启动 SDK。 -## 构建与烧录 - -在工程根目录激活 ESP-IDF v5.5.2 后构建中英文固件: - -```sh -python3 scripts/build_all.py --board bread-compact-wifi-lcd --language both -``` - -合并固件输出为 `releases/bread-compact-wifi-lcd-zh-CN.bin` 和对应的 `en-US.bin`。 -批量脚本默认清理其专用构建和输出目录,详见[构建说明](../../../../README.zh-CN.md#构建)。 - -使用独立构建目录和 sdkconfig 的手动构建、烧录示例,将 `PORT` 替换为本机串口设备: - -```sh -idf.py -B build/bread-compact-wifi-lcd \ - -DMYBOT_BOARD=bread-compact-wifi-lcd \ - -DSDKCONFIG=build/bread-compact-wifi-lcd/sdkconfig build -idf.py -B build/bread-compact-wifi-lcd -p PORT flash monitor -``` - -该固定 profile 的中英文构建支持已在 ESP-IDF v5.5.2 验证,真机验证尚未完成。目标设备仍需 -核对模组与检测容量、屏幕颜色/方向、PWM 背光、音频速度/音调、全双工交互及重复配网。 -验收范围见[平台移植说明](../../../../docs/BOARD_PORTING.zh-CN.md)。 +构建、烧录与验证状态见[板卡索引](../README.md)和[验证矩阵](../../../../docs/VALIDATION.md)。 diff --git a/components/mybot_platform/boards/esp-vocat/README.md b/components/mybot_platform/boards/esp-vocat/README.md index 41401f5..872a569 100644 --- a/components/mybot_platform/boards/esp-vocat/README.md +++ b/components/mybot_platform/boards/esp-vocat/README.md @@ -43,32 +43,5 @@ D0-D3 GPIO46/GPIO13/GPIO11/GPIO12,背光为 GPIO44,触摸中断为 GPIO10。 CST816S 使用中断触发读取,仅在按住时定时检查长按,不持续轮询空闲触摸。当前配置关闭 触摸 ID 寄存器读取,以兼容不响应该寄存器的固件批次。 -## 编译与烧录 - -在工程根目录使用 ESP-IDF 5.5.2: - -```sh -source /path/to/esp-idf/export.sh -python3 scripts/build_all.py --board esp-vocat --language both -``` - -脚本自动启用 LVGL,生成 `releases/esp-vocat-zh-CN.bin` 和 -`releases/esp-vocat-en-US.bin`,默认清理脚本管理的 `build/` 和 `releases/`。 - -需要独立构建、烧录并查看控制台时,可使用: - -```sh -idf.py -B build/esp-vocat \ - -DMYBOT_BOARD=esp-vocat \ - -DSDKCONFIG=build/esp-vocat/sdkconfig build flash monitor -``` - -使用原生 USB 数据接口并打开硬件电源;如需指定端口,在命令中增加 `-p` 参数。 -其他板型必须使用不同的构建目录和 sdkconfig。 - -## 支持边界 - -第二麦克风、播放参考通道、本地 AEC、电量计、IMU、电容控制、SD 卡、LED、关机和低功耗 -尚未集成。硬件能力不等同于本工程已实现的功能。 -两个 PCB 版本的电源、引脚映射、音频和触摸均需在对应实物上验证;构建通过不能替代真机测试。 -完整说明见[工程文档](../../../../README.zh-CN.md)和[平台移植说明](../../../../docs/BOARD_PORTING.zh-CN.md)。 +烧录时使用原生 USB 并打开硬件电源。构建、烧录与验证状态见[板卡索引](../README.md)和 +[验证矩阵](../../../../docs/VALIDATION.md)。 diff --git a/components/mybot_platform/boards/esp32-s3-touch-amoled-1.75/README.md b/components/mybot_platform/boards/esp32-s3-touch-amoled-1.75/README.md index 676132f..dbe7527 100644 --- a/components/mybot_platform/boards/esp32-s3-touch-amoled-1.75/README.md +++ b/components/mybot_platform/boards/esp32-s3-touch-amoled-1.75/README.md @@ -40,31 +40,6 @@ 未保存 Wi-Fi 信息时自动进入配网,屏幕显示热点名称并播放提示音;按屏幕提示连接热点 完成配置。触摸与 Boot 由板级常驻模块管理,SDK 停止期间仍可请求配网。 -## 编译与烧录 - -在工程根目录使用 ESP-IDF 5.5.2: - -```sh -source /path/to/esp-idf/export.sh -python3 scripts/build_all.py --board esp32-s3-touch-amoled-1.75 --language both -``` - -脚本自动启用 LVGL,生成 `releases/esp32-s3-touch-amoled-1.75-zh-CN.bin` 和 -`releases/esp32-s3-touch-amoled-1.75-en-US.bin`,默认清理脚本管理的 `build/` 和 `releases/`。 - -需要独立构建、烧录并查看控制台时,可使用: - -```sh -idf.py -B build/esp32-s3-touch-amoled-1.75 \ - -DMYBOT_BOARD=esp32-s3-touch-amoled-1.75 \ - -DSDKCONFIG=build/esp32-s3-touch-amoled-1.75/sdkconfig build flash monitor -``` - -如需指定端口,在命令中增加 `-p` 参数。其他板型必须使用不同的构建目录和 sdkconfig。 - -## 支持边界 - 本板与 1.75C 共用生命周期、音频和输入实现,但 MCLK、屏幕复位、触摸复位和 TCA9554 -配置不同。RTC、IMU、TF 卡、电池状态、自动休眠、关机、播放参考通道和本地 AEC 尚未集成。 -当前支持范围为构建集成;电源时序、音频 slot、显示颜色/方向和触摸仍需在匹配实物上验证。 -完整说明见[工程文档](../../../../README.zh-CN.md)和[平台移植说明](../../../../docs/BOARD_PORTING.zh-CN.md)。 +配置不同。构建、烧录与验证状态见[板卡索引](../README.md)和 +[验证矩阵](../../../../docs/VALIDATION.md)。 diff --git a/components/mybot_platform/boards/esp32-s3-touch-amoled-1.75c/README.md b/components/mybot_platform/boards/esp32-s3-touch-amoled-1.75c/README.md index bf4f7dc..c48275e 100644 --- a/components/mybot_platform/boards/esp32-s3-touch-amoled-1.75c/README.md +++ b/components/mybot_platform/boards/esp32-s3-touch-amoled-1.75c/README.md @@ -42,31 +42,6 @@ CS GPIO12、D0-D3 GPIO4/GPIO5/GPIO6/GPIO7,以及 CST9217 INT GPIO11。 未保存 Wi-Fi 信息时自动进入配网,屏幕显示热点名称并播放提示音;按屏幕提示连接热点 完成配置。触摸与 Boot 由板级常驻模块管理,SDK 停止期间仍可请求配网。 -## 编译与烧录 - -在工程根目录使用 ESP-IDF 5.5.2: - -```sh -source /path/to/esp-idf/export.sh -python3 scripts/build_all.py --board esp32-s3-touch-amoled-1.75c --language both -``` - -脚本自动启用 LVGL,生成 `releases/esp32-s3-touch-amoled-1.75c-zh-CN.bin` 和 -`releases/esp32-s3-touch-amoled-1.75c-en-US.bin`,默认清理脚本管理的 `build/` 和 `releases/`。 - -需要独立构建、烧录并查看控制台时,可使用: - -```sh -idf.py -B build/esp32-s3-touch-amoled-1.75c \ - -DMYBOT_BOARD=esp32-s3-touch-amoled-1.75c \ - -DSDKCONFIG=build/esp32-s3-touch-amoled-1.75c/sdkconfig build flash monitor -``` - -如需指定端口,在命令中增加 `-p` 参数。其他板型必须使用不同的构建目录和 sdkconfig。 - -## 支持边界 - 本板复用 `esp32-s3-touch-amoled-1.75-common` 的板级生命周期、音频和输入实现,保留独立 -板型身份。RTC、IMU、TF 卡、电池状态、自动休眠、关机、播放参考通道和本地 AEC 尚未集成。 -当前支持范围为构建集成;电源时序、音频 slot、显示颜色/方向和触摸仍需在匹配实物上验证。 -完整说明见[工程文档](../../../../README.zh-CN.md)和[平台移植说明](../../../../docs/BOARD_PORTING.zh-CN.md)。 +板型身份,并且不探测或依赖 TCA9554。构建、烧录与验证状态见[板卡索引](../README.md)和 +[验证矩阵](../../../../docs/VALIDATION.md)。 diff --git a/components/mybot_platform/boards/esp32-s3-touch-amoled-2.16/README.md b/components/mybot_platform/boards/esp32-s3-touch-amoled-2.16/README.md index 5618cc8..bc3f987 100644 --- a/components/mybot_platform/boards/esp32-s3-touch-amoled-2.16/README.md +++ b/components/mybot_platform/boards/esp32-s3-touch-amoled-2.16/README.md @@ -20,8 +20,7 @@ | 视频 | 未集成摄像头采集,不支持 `CONFIG_MYBOT_ENABLE_VIDEO` | 公共 I2C0 使用 SDA GPIO15、SCL GPIO14,先完成 AXP2101 上电,再挂接屏幕、触摸和音频设备。 -本 profile 可选探测地址 `0x20` 的 TCA9554,未发现时可以继续初始化;实际板上是否搭载 -该器件仍需确认。 +本 profile 可选探测地址 `0x20` 的 TCA9554,未发现时可以继续初始化。 | 信号 | GPIO | | --- | --- | @@ -42,32 +41,5 @@ 未保存 Wi-Fi 信息时自动进入配网,屏幕显示热点名称并播放提示音;按屏幕提示连接热点 完成配置。触摸与 Boot 由板级常驻模块管理,SDK 停止期间仍可请求配网。 -## 编译与烧录 - -在工程根目录使用 ESP-IDF 5.5.2: - -```sh -source /path/to/esp-idf/export.sh -python3 scripts/build_all.py --board esp32-s3-touch-amoled-2.16 --language both -``` - -脚本自动启用 LVGL,生成 `releases/esp32-s3-touch-amoled-2.16-zh-CN.bin` 和 -`releases/esp32-s3-touch-amoled-2.16-en-US.bin`,默认清理脚本管理的 `build/` 和 `releases/`。 - -需要独立构建、烧录并查看控制台时,可使用: - -```sh -idf.py -B build/esp32-s3-touch-amoled-2.16 \ - -DMYBOT_BOARD=esp32-s3-touch-amoled-2.16 \ - -DSDKCONFIG=build/esp32-s3-touch-amoled-2.16/sdkconfig build flash monitor -``` - -如需指定端口,在命令中增加 `-p` 参数。其他板型必须使用不同的构建目录和 sdkconfig。 - -## 支持边界 - -中英文固件构建已在 ESP-IDF 5.5.2 验证,真机验证尚未完成。发布前需核对实际 Flash/PSRAM -容量,验证电源时序、480 × 480 显示颜色/方向、触摸和 16 kHz 双向音频。若硬件需要其他 -音频采样率,转换应留在平台驱动内,SDK 的 16 kHz 单声道 PCM 契约保持不变。 -RTC、IMU、TF 卡、电池状态、自动休眠、关机、播放参考通道和本地 AEC 尚未集成。 -完整说明见[工程文档](../../../../README.zh-CN.md)和[平台移植说明](../../../../docs/BOARD_PORTING.zh-CN.md)。 +若硬件需要其他音频采样率,转换应留在平台驱动内,SDK 的 16 kHz 单声道 PCM 契约保持不变。 +构建、烧录与验证状态见[板卡索引](../README.md)和[验证矩阵](../../../../docs/VALIDATION.md)。 diff --git a/components/mybot_platform/boards/m5stack-core-s3/README.md b/components/mybot_platform/boards/m5stack-core-s3/README.md index d518c83..593e9a2 100644 --- a/components/mybot_platform/boards/m5stack-core-s3/README.md +++ b/components/mybot_platform/boards/m5stack-core-s3/README.md @@ -25,34 +25,5 @@ SCLK GPIO36、CS GPIO3、DC GPIO35。 无已保存的 Wi-Fi 信息时自动进入配网并显示热点名称、播放提示音。已有网络时联网后启动 SDK;长按触摸会先停止 SDK 再配网。设备音量保存在 NVS,重启后恢复。 -## 构建与烧录 - -在仓库根目录使用 ESP-IDF v5.5.2: - -```sh -source /path/to/esp-idf/export.sh -python3 scripts/build_all.py --board m5stack-core-s3 --language both -``` - -脚本默认开启视频,输出 `releases/m5stack-core-s3-zh-CN-video.bin` 和对应英文固件。 -需要关闭视频时追加 `--video off`。CoreS3-SE 不带 GC0308,不能使用视频固件。 -构建脚本的清理行为见[板卡索引](../README.md)。 - -直接构建中文视频固件并烧录时,使用独立目录;将串口替换为本机设备: - -```sh -idf.py -B build/m5stack-core-s3 \ - -DMYBOT_BOARD=m5stack-core-s3 \ - -DSDKCONFIG=build/m5stack-core-s3/sdkconfig \ - -DSDKCONFIG_DEFAULTS="sdkconfig.defaults;ci/ptime60.defaults;ci/video.defaults" build -idf.py -B build/m5stack-core-s3 -p /dev/ttyUSB0 flash monitor -``` - -英文直接构建需在新目录的 defaults 列表追加 `;ci/en-us.defaults`。 - -## 验证范围 - -已有音频和摄像头通路完成过真机验证;当前像素眼镜 UI、采集调度和 DMA 配置仍需按对应 -文档回归。构建成功不等于硬件验收。详见[像素眼镜 UI](../../../../docs/CORES3_UI.zh-CN.md)、 -[摄像头上行](../../../../docs/CORES3_VIDEO.zh-CN.md)及 -[音频对照测试](../../../../docs/CORES3_AUDIO_TEST.zh-CN.md)。 +CoreS3-SE 不带 GC0308,不能使用视频固件。构建、烧录与验证状态见[板卡索引](../README.md)、 +[像素眼镜 UI](../../../../docs/CORES3_UI.zh-CN.md)和[验证矩阵](../../../../docs/VALIDATION.md)。 diff --git a/components/mybot_platform/boards/m5stack-stick-s3/README.md b/components/mybot_platform/boards/m5stack-stick-s3/README.md index 099795b..8d1e7a7 100644 --- a/components/mybot_platform/boards/m5stack-stick-s3/README.md +++ b/components/mybot_platform/boards/m5stack-stick-s3/README.md @@ -27,31 +27,4 @@ LCD SPI3 为 MOSI GPIO39、SCLK GPIO40、CS GPIO41、DC GPIO45、RESET GPIO21; 当前 ES8311 硬件音量按逻辑值的 60% 映射。无 Wi-Fi 信息时自动进入配网并显示热点名称、 播放提示音;长按主按键会先停止 SDK 再重新配网。 -## 构建与烧录 - -在仓库根目录使用 ESP-IDF v5.5.2: - -```sh -source /path/to/esp-idf/export.sh -python3 scripts/build_all.py --board m5stack-stick-s3 --language both -``` - -输出 `releases/m5stack-stick-s3-zh-CN.bin` 和对应英文固件;LVGL 自动启用。 -构建脚本的清理行为见[板卡索引](../README.md)。 - -直接构建中文固件并烧录时,使用独立目录;将串口替换为本机设备: - -```sh -idf.py -B build/m5stack-stick-s3 \ - -DMYBOT_BOARD=m5stack-stick-s3 \ - -DSDKCONFIG=build/m5stack-stick-s3/sdkconfig \ - -DSDKCONFIG_DEFAULTS="sdkconfig.defaults;ci/ptime60.defaults" build -idf.py -B build/m5stack-stick-s3 -p /dev/ttyUSB0 flash monitor -``` - -## 验证范围 - -当前 profile 尚未完成真机验收,需验证电源时序、16 kHz 双向音频、按键与屏幕颜色/方向。 -GPIO12、IMU、红外、电池状态、关机手势和低功耗未接入。详见 -[平台移植](../../../../docs/BOARD_PORTING.zh-CN.md)及 -[平台 UI](../../../../docs/PLATFORM_UI.zh-CN.md)。 +构建、烧录与验证状态见[板卡索引](../README.md)和[验证矩阵](../../../../docs/VALIDATION.md)。 diff --git a/components/mybot_platform/boards/respeaker-flex-xvf3800-circular4-xiao/README.md b/components/mybot_platform/boards/respeaker-flex-xvf3800-circular4-xiao/README.md index 8858955..6f25430 100644 --- a/components/mybot_platform/boards/respeaker-flex-xvf3800-circular4-xiao/README.md +++ b/components/mybot_platform/boards/respeaker-flex-xvf3800-circular4-xiao/README.md @@ -31,31 +31,5 @@ Cloud AEC,避免重复处理。音量由平台软件增益控制并保存在 N 36 轮询读取。无 Wi-Fi 信息时自动创建配置热点并播放提示音;手动配网前先停止 SDK。 设备没有屏幕,配网与配对状态通过语音和控制台日志查看。 -## 构建与烧录 - -在仓库根目录使用 ESP-IDF v5.5.2: - -```sh -source /path/to/esp-idf/export.sh -python3 scripts/build_all.py --board respeaker-flex-xvf3800-circular4-xiao --language both -``` - -输出 `releases/respeaker-flex-xvf3800-circular4-xiao-zh-CN.bin` 和对应英文固件。 -构建脚本的清理行为见[板卡索引](../README.md)。 - -直接构建中文固件并烧录时,使用独立目录;将串口替换为本机 USB Serial/JTAG 设备: - -```sh -idf.py -B build/respeaker-flex-xvf3800-circular4-xiao \ - -DMYBOT_BOARD=respeaker-flex-xvf3800-circular4-xiao \ - -DSDKCONFIG=build/respeaker-flex-xvf3800-circular4-xiao/sdkconfig \ - -DSDKCONFIG_DEFAULTS="sdkconfig.defaults;ci/ptime60.defaults" build -idf.py -B build/respeaker-flex-xvf3800-circular4-xiao -p /dev/ttyACM0 flash monitor -``` - -## 验证范围 - -当前 profile 尚未完成真机验收。需验证 XVF 固件版本、时钟方向、通道路由、双向音频、 -声学处理、按键与重复配网。构建成功不能证明这些硬件行为正确。 -详见[平台移植文档](../../../../docs/BOARD_PORTING.zh-CN.md)及 -[项目说明](../../../../README.zh-CN.md)。 +通过 USB Serial/JTAG 构建和烧录;具体命令见[板卡索引](../README.md),验证状态见 +[验证矩阵](../../../../docs/VALIDATION.md)。 diff --git a/components/mybot_platform/boards/sensecap-watcher/README.md b/components/mybot_platform/boards/sensecap-watcher/README.md index 99f9e85..6a6968e 100644 --- a/components/mybot_platform/boards/sensecap-watcher/README.md +++ b/components/mybot_platform/boards/sensecap-watcher/README.md @@ -26,17 +26,9 @@ LCD QSPI 为 CLK GPIO7、D0 GPIO9、D1 GPIO1、D2 GPIO14、D3 GPIO13、CS GPIO45 降低,旋转方向需实机确认。音量保存到 NVS。无 Wi-Fi 信息时自动进入配网并显示热点名称、 播放提示音;手动配网前先停止 SDK。 -## 构建与烧录 +## 出厂数据保护 -在仓库根目录使用 ESP-IDF v5.5.2: - -```sh -source /path/to/esp-idf/export.sh -python3 scripts/build_all.py --board sensecap-watcher --language both -``` - -脚本输出 `releases/sensecap-watcher-zh-CN.bin` 和对应英文合并镜像;清理行为见 -[板卡索引](../README.md)。为保留出厂分区,设备烧录请使用下面的独立构建与 `idf.py flash`, +为保留出厂分区,设备必须使用[板卡索引](../README.md)中的独立构建与 `idf.py flash`, 不要直接向整片 Flash 写入合并镜像。 首次烧录前备份出厂分区,将串口替换为本机设备,并妥善保存备份: @@ -48,19 +40,5 @@ python -m esptool --chip esp32s3 --port /dev/ttyUSB0 --baud 2000000 \ ``` 出厂分区 `nvsfactory` 从 `0x9000` 开始,长度为 200 KiB。禁止执行 `erase-flash` 或使用 -其他板型的分区表。下面的标准烧录流程不会写入 `nvsfactory`: - -```sh -idf.py -B build/sensecap-watcher \ - -DMYBOT_BOARD=sensecap-watcher \ - -DSDKCONFIG=build/sensecap-watcher/sdkconfig \ - -DSDKCONFIG_DEFAULTS="sdkconfig.defaults;ci/ptime60.defaults" build -idf.py -B build/sensecap-watcher -p /dev/ttyUSB0 flash monitor -``` - -## 验证范围 - -当前 profile 尚未完成真机验收;需验证电源时序、codec 的 16 kHz 工作模式、双向音频、 -编码器、配网和显示。摄像头、触摸、LED、电池状态、关机及低功耗尚未接入。 -详见[平台移植](../../../../docs/BOARD_PORTING.zh-CN.md)及 -[平台 UI](../../../../docs/PLATFORM_UI.zh-CN.md)。 +其他板型的分区表。标准 `idf.py flash` 不会写入 `nvsfactory`。构建与验证状态见 +[板卡索引](../README.md)和[验证矩阵](../../../../docs/VALIDATION.md)。 diff --git a/components/mybot_platform/boards/sensecap-watcher/README_en.md b/components/mybot_platform/boards/sensecap-watcher/README_en.md index 1998df7..97c0105 100644 --- a/components/mybot_platform/boards/sensecap-watcher/README_en.md +++ b/components/mybot_platform/boards/sensecap-watcher/README_en.md @@ -28,19 +28,10 @@ verify physical rotation on the device. Volume is persisted in NVS. With no save credentials, provisioning starts automatically, displays the hotspot name and plays a prompt. Manual provisioning stops SDK before entering setup. -## Build and flash +## Factory-data protection -Use ESP-IDF v5.5.2 from the repository root: - -```sh -source /path/to/esp-idf/export.sh -python3 scripts/build_all.py --board sensecap-watcher --language both -``` - -The script produces `releases/sensecap-watcher-zh-CN.bin` and its English merged image. -See the [board index](../README.md) for cleanup behavior. To preserve factory data, flash this -device through the dedicated build and `idf.py flash` below; do not write a merged image -across the entire Flash. +To preserve factory data, use the dedicated build and `idf.py flash` instructions in the +[board index](../README.md); do not write a merged image across the entire Flash. Before the first flash, back up the factory partition. Replace the serial port with your device's port and keep the backup safe: @@ -52,21 +43,6 @@ python -m esptool --chip esp32s3 --port /dev/ttyUSB0 --baud 2000000 \ ``` The `nvsfactory` partition starts at `0x9000` and occupies 200 KiB. Do not run `erase-flash` -or substitute another board's partition table. Standard flashing below does not write -`nvsfactory`: - -```sh -idf.py -B build/sensecap-watcher-en-US \ - -DMYBOT_BOARD=sensecap-watcher \ - -DSDKCONFIG=build/sensecap-watcher-en-US/sdkconfig \ - -DSDKCONFIG_DEFAULTS="sdkconfig.defaults;ci/ptime60.defaults;ci/en-us.defaults" build -idf.py -B build/sensecap-watcher-en-US -p /dev/ttyUSB0 flash monitor -``` - -## Validation scope - -This profile has not completed real-device acceptance. Verify power sequencing, the codecs' -16 kHz mode, bidirectional audio, the encoder, provisioning and the display. Camera, touch, -LEDs, battery status, shutdown and low-power support are not integrated. See -[board porting](../../../../docs/BOARD_PORTING.md) and -[platform UI](../../../../docs/PLATFORM_UI.md). +or substitute another board's partition table. Standard `idf.py flash` does not write +`nvsfactory`. Build and validation status: see the [board index](../README.md) and +[validation matrix](../../../../docs/VALIDATION.md). diff --git a/components/mybot_platform/boards/xingzhi-cube-1.54tft-wifi/README.md b/components/mybot_platform/boards/xingzhi-cube-1.54tft-wifi/README.md index da744ce..8b77341 100644 --- a/components/mybot_platform/boards/xingzhi-cube-1.54tft-wifi/README.md +++ b/components/mybot_platform/boards/xingzhi-cube-1.54tft-wifi/README.md @@ -9,8 +9,8 @@ | 项目 | 当前实现 | | --- | --- | | 主控 | ESP32-S3 | -| Flash | 16 MB QIO profile;实际容量需在目标设备核对 | -| PSRAM | Octal,80 MHz;实际容量需在目标设备核对 | +| Flash | 16 MB QIO profile | +| PSRAM | Octal,80 MHz | | 分区 | [16 MB 分区表](../../../../partitions/v2/16m.csv),双 OTA 应用分区及 8 MB assets 分区 | | 控制台 | 未覆盖 ESP-IDF 默认控制台配置,使用 UART0 | | 音频 | 独立麦克风/扬声器 I2S,16 kHz 单声道;软件音量及 NVS 持久化 | @@ -46,26 +46,4 @@ SDK 音频边界为 16 kHz、单声道、signed-16 PCM;物理标准 I2S 使用 连接该热点后访问 `http://192.168.4.1` 配置 Wi-Fi。进入配网时播放对应语言提示音,取得 可用 IP 后才启动 SDK。 -## 构建与烧录 - -在工程根目录激活 ESP-IDF v5.5.2 后构建中英文固件: - -```sh -python3 scripts/build_all.py --board xingzhi-cube-1.54tft-wifi --language both -``` - -合并固件输出为 `releases/xingzhi-cube-1.54tft-wifi-zh-CN.bin` 和对应的 `en-US.bin`。 -批量脚本默认清理其专用构建和输出目录,详见[构建说明](../../../../README.zh-CN.md#构建)。 - -使用独立构建目录和 sdkconfig 的手动构建、烧录示例,将 `PORT` 替换为本机串口设备: - -```sh -idf.py -B build/xingzhi-cube-1.54tft-wifi \ - -DMYBOT_BOARD=xingzhi-cube-1.54tft-wifi \ - -DSDKCONFIG=build/xingzhi-cube-1.54tft-wifi/sdkconfig build -idf.py -B build/xingzhi-cube-1.54tft-wifi -p PORT flash monitor -``` - -构建成功不代表实机验收。实际 Flash/PSRAM 容量、GPIO21 供电保持、PWM 背光、显示方向、 -音频速度/音调和同时采集播放均需在目标硬件核对;验收范围见 -[平台移植说明](../../../../docs/BOARD_PORTING.zh-CN.md)。 +构建、烧录与验证状态见[板卡索引](../README.md)和[验证矩阵](../../../../docs/VALIDATION.md)。 diff --git a/components/mybot_platform/boards/zhengchen-1.54tft-ml307/README.md b/components/mybot_platform/boards/zhengchen-1.54tft-ml307/README.md index 551d03f..169f046 100644 --- a/components/mybot_platform/boards/zhengchen-1.54tft-ml307/README.md +++ b/components/mybot_platform/boards/zhengchen-1.54tft-ml307/README.md @@ -10,7 +10,7 @@ | --- | --- | | 主控 | ESP32-S3 | | Flash | 16 MB,QIO | -| PSRAM | Octal,80 MHz;实际容量以启动日志为准 | +| PSRAM | Octal,80 MHz | | 分区 | [16 MB 分区表](../../../../partitions/v2/16m.csv),双 OTA 应用分区及 8 MB assets 分区 | | 控制台 | 未覆盖 ESP-IDF 默认控制台配置,使用 UART0 | | 音频 | 独立麦克风/扬声器 I2S,16 kHz 单声道;软件音量及 NVS 持久化 | @@ -50,26 +50,4 @@ SDK 音频边界为 16 kHz、单声道、signed-16 PCM;物理标准 I2S 使用 连接该热点后访问 `http://192.168.4.1` 配置 Wi-Fi。进入配网时播放对应语言提示音,取得 可用 IP 后才启动 SDK。 -## 构建与烧录 - -在工程根目录激活 ESP-IDF v5.5.2 后构建中英文固件: - -```sh -python3 scripts/build_all.py --board zhengchen-1.54tft-ml307 --language both -``` - -合并固件输出为 `releases/zhengchen-1.54tft-ml307-zh-CN.bin` 和对应的 `en-US.bin`。 -批量脚本默认清理其专用构建和输出目录,详见[构建说明](../../../../README.zh-CN.md#构建)。 - -需要使用 `idf.py` 逐步构建、烧录时,使用独立的构建目录和 sdkconfig: - -```sh -idf.py -B build/zhengchen-1.54tft-ml307 \ - -DMYBOT_BOARD=zhengchen-1.54tft-ml307 \ - -DSDKCONFIG=build/zhengchen-1.54tft-ml307/sdkconfig build -idf.py -B build/zhengchen-1.54tft-ml307 -p /dev/tty.wchusbserial1430 flash monitor -``` - -上述串口名为该征辰板在 macOS 上的设备名,其他系统按实际枚举结果选择端口。构建成功 -不代表实机验收;音频、屏幕颜色/方向、按键及重复配网应在目标设备上验证,参见 -[平台移植说明](../../../../docs/BOARD_PORTING.zh-CN.md)。 +构建、烧录与验证状态见[板卡索引](../README.md)和[验证矩阵](../../../../docs/VALIDATION.md)。 diff --git a/components/mybot_platform/boards/zhengchen-1.54tft-wifi/README.md b/components/mybot_platform/boards/zhengchen-1.54tft-wifi/README.md index f356cb4..1270d3d 100644 --- a/components/mybot_platform/boards/zhengchen-1.54tft-wifi/README.md +++ b/components/mybot_platform/boards/zhengchen-1.54tft-wifi/README.md @@ -10,7 +10,7 @@ | --- | --- | | 主控 | ESP32-S3 | | Flash | 16 MB,QIO | -| PSRAM | Octal,80 MHz;实际容量以启动日志为准 | +| PSRAM | Octal,80 MHz | | 分区 | [16 MB 分区表](../../../../partitions/v2/16m.csv),双 OTA 应用分区及 8 MB assets 分区 | | 控制台 | 未覆盖 ESP-IDF 默认控制台配置,使用 UART0 | | 音频 | 独立麦克风/扬声器 I2S,16 kHz 单声道;软件音量及 NVS 持久化 | @@ -48,26 +48,4 @@ SDK 音频边界为 16 kHz、单声道、signed-16 PCM;物理标准 I2S 使用 连接该热点后访问 `http://192.168.4.1` 配置 Wi-Fi。进入配网时播放对应语言提示音,取得 可用 IP 后才启动 SDK。 -## 构建与烧录 - -在工程根目录激活 ESP-IDF v5.5.2 后构建中英文固件: - -```sh -python3 scripts/build_all.py --board zhengchen-1.54tft-wifi --language both -``` - -合并固件输出为 `releases/zhengchen-1.54tft-wifi-zh-CN.bin` 和对应的 `en-US.bin`。 -批量脚本默认清理其专用构建和输出目录,详见[构建说明](../../../../README.zh-CN.md#构建)。 - -需要使用 `idf.py` 逐步构建、烧录时,使用独立的构建目录和 sdkconfig: - -```sh -idf.py -B build/zhengchen-1.54tft-wifi \ - -DMYBOT_BOARD=zhengchen-1.54tft-wifi \ - -DSDKCONFIG=build/zhengchen-1.54tft-wifi/sdkconfig build -idf.py -B build/zhengchen-1.54tft-wifi -p /dev/tty.wchusbserial1430 flash monitor -``` - -上述串口名为该征辰板在 macOS 上的设备名,其他系统按实际枚举结果选择端口。构建成功 -不代表实机验收;音频、屏幕颜色/方向、按键及重复配网应在目标设备上验证,参见 -[平台移植说明](../../../../docs/BOARD_PORTING.zh-CN.md)。 +构建、烧录与验证状态见[板卡索引](../README.md)和[验证矩阵](../../../../docs/VALIDATION.md)。 diff --git a/components/mybot_platform/src/drivers/display/README.md b/components/mybot_platform/src/drivers/display/README.md index 9e345ee..a42c526 100644 --- a/components/mybot_platform/src/drivers/display/README.md +++ b/components/mybot_platform/src/drivers/display/README.md @@ -18,10 +18,10 @@ The renderer consumes semantic `mybot_lcd_content_t`; it does not own Wi-Fi, aud For the provisioning title it copies the active SoftAP name through the Wi-Fi service's internal snapshot getter. The getter does not acquire the provisioning-operation lock or call the display. LVGL scrolls overflowing provisioning labels and stops their animations when leaving that screen. -The CoreS3 adapter also owns copied one-shot expression requests and monotonic hold/phase timing; -the existing LVGL task performs all drawing. Expressions are LCD-only. CoreS3's light-theme -option remains compatible but its appearance is fixed process gray. See -[`docs/CORES3_UI.md`](../../../../../docs/CORES3_UI.md) for all 23 faces and MCP timing. +The CoreS3 adapter owns monotonic automatic-expression phase and opener timing; the existing +LVGL task performs all drawing. Expressions are LCD-only. CoreS3's light-theme option remains +compatible but its appearance is fixed process gray. See +[`docs/CORES3_UI.md`](../../../../../docs/CORES3_UI.md) for all 23 faces and state timing. LVGL is the only renderer for all display boards; AtomEchoS3R and ReSpeaker Flex remain headless. `CONFIG_MYBOT_LVGL_UI` is derived from the selected board and is not a user-facing switch. diff --git a/components/mybot_platform/src/drivers/display/adapters/lvgl/ili9342_lvgl_adapter.cc b/components/mybot_platform/src/drivers/display/adapters/lvgl/ili9342_lvgl_adapter.cc index 761114a..094227e 100644 --- a/components/mybot_platform/src/drivers/display/adapters/lvgl/ili9342_lvgl_adapter.cc +++ b/components/mybot_platform/src/drivers/display/adapters/lvgl/ili9342_lvgl_adapter.cc @@ -42,8 +42,8 @@ struct Context { #if MYBOT_CORES3_PIXEL_UI mybot_expression_policy_t policy{}; mybot_display_runtime_status_t runtime{}; - /* Only new foreground commands/workflow changes advance this generation. - * Overlay refreshes must not affect the foreground display clock. */ + /* Only workflow changes advance this generation. Overlay refreshes must not + * affect the foreground display clock. */ uint32_t expression_generation = 0; #endif }; @@ -339,26 +339,6 @@ int render(void *opaque, const mybot_lcd_content_t *content) { memcpy(snapshot.pair_code, content->pair_code, length); } #if MYBOT_CORES3_PIXEL_UI - mybot_expression_t expression = MYBOT_EXPRESSION_NEUTRAL; - const uint32_t emotion = snapshot.indicators & MYBOT_LCD_INDICATOR_EMOTION_MASK; - switch (emotion) { - case MYBOT_LCD_INDICATOR_NONE: - break; - case MYBOT_LCD_INDICATOR_HAPPY: - expression = MYBOT_EXPRESSION_HAPPY; - break; - case MYBOT_LCD_INDICATOR_SAD: - expression = MYBOT_EXPRESSION_SAD; - break; - case MYBOT_LCD_INDICATOR_ANGRY: - expression = MYBOT_EXPRESSION_ANNOYED; - break; - case MYBOT_LCD_INDICATOR_SURPRISED: - expression = MYBOT_EXPRESSION_SURPRISED; - break; - default: - return -1; - } const uint32_t now = (uint32_t)(esp_timer_get_time() / 1000); #endif if (!lock_lifecycle()) { @@ -370,15 +350,10 @@ int render(void *opaque, const mybot_lcd_content_t *content) { #if MYBOT_CORES3_PIXEL_UI const bool screen_changed = context.policy.screen != snapshot.screen; mybot_expression_policy_update(&context.policy, &snapshot, now); - if (emotion) { - (void)mybot_expression_policy_mcp(&context.policy, expression); - } - if (screen_changed || emotion) { + if (screen_changed) { ++context.expression_generation; context.pending = true; } - /* Consume one-shot commands before retaining the coalesced snapshot. */ - snapshot.indicators &= ~MYBOT_LCD_INDICATOR_EMOTION_MASK; #endif if (memcmp(&snapshot, &context.latest, sizeof(snapshot)) != 0) { context.latest = snapshot; diff --git a/components/mybot_platform/src/internal/display/expression_policy.h b/components/mybot_platform/src/internal/display/expression_policy.h index b96bdb5..f57f11e 100644 --- a/components/mybot_platform/src/internal/display/expression_policy.h +++ b/components/mybot_platform/src/internal/display/expression_policy.h @@ -13,8 +13,6 @@ typedef enum { MYBOT_EXPRESSION_SOURCE_STATE = 0, MYBOT_EXPRESSION_SOURCE_OPENING, - MYBOT_EXPRESSION_SOURCE_MCP, - MYBOT_EXPRESSION_SOURCE_LOCAL, } mybot_expression_source_t; typedef struct { @@ -77,45 +75,9 @@ static inline void mybot_expression_policy_update(mybot_expression_policy_t *pol } } -static inline uint32_t mybot_expression_mcp_hold_ms(mybot_expression_t expression) { - switch (expression) { - case MYBOT_EXPRESSION_HAPPY: - return 2000U; - case MYBOT_EXPRESSION_SAD: - return 3000U; - case MYBOT_EXPRESSION_ANNOYED: - return 1200U; - case MYBOT_EXPRESSION_SURPRISED: - return 800U; - default: - return 0; - } -} - -static inline bool mybot_expression_policy_mcp(mybot_expression_policy_t *policy, - mybot_expression_t expression) { - if (policy->screen != MYBOT_LCD_SCREEN_IN_CONVERSATION || - !mybot_expression_mcp_hold_ms(expression)) - return false; - policy->source = MYBOT_EXPRESSION_SOURCE_MCP; - policy->foreground = expression; - policy->foreground_pending = true; /* Same name is still a new command. */ - return true; -} - -static inline bool mybot_expression_policy_local(mybot_expression_policy_t *policy, - mybot_expression_t expression) { - if (policy->source == MYBOT_EXPRESSION_SOURCE_LOCAL && policy->foreground == expression) - return false; - policy->source = MYBOT_EXPRESSION_SOURCE_LOCAL; - policy->foreground = expression; - policy->foreground_pending = false; /* Persistent; identical art need not replay. */ - return true; -} - /* The UI owner calls this every bounded tick, including without a new render. * Pending foreground clocks start only after successful display submission. - * Hold time excludes the entering transition, including for the 300 ms opener. */ + * The 300 ms opener hold excludes its entering transition. */ static inline bool mybot_expression_policy_select(mybot_expression_policy_t *policy, uint32_t now, uint32_t transition_ms, mybot_expression_t *expression, bool *replay) { @@ -123,13 +85,9 @@ static inline bool mybot_expression_policy_select(mybot_expression_policy_t *pol if (policy->screen != MYBOT_LCD_SCREEN_READY && policy->screen != MYBOT_LCD_SCREEN_IN_CONVERSATION) return false; - if (policy->source == MYBOT_EXPRESSION_SOURCE_OPENING || - policy->source == MYBOT_EXPRESSION_SOURCE_MCP) { - uint32_t hold = policy->source == MYBOT_EXPRESSION_SOURCE_OPENING - ? 300U - : mybot_expression_mcp_hold_ms(policy->foreground); + if (policy->source == MYBOT_EXPRESSION_SOURCE_OPENING) { if (!policy->foreground_pending && - (uint32_t)(now - policy->foreground_since) >= hold + transition_ms) + (uint32_t)(now - policy->foreground_since) >= 300U + transition_ms) (void)mybot_expression_policy_clear(policy); } if (policy->source != MYBOT_EXPRESSION_SOURCE_STATE) { @@ -158,10 +116,6 @@ static inline const char *mybot_expression_source_name(mybot_expression_source_t switch (source) { case MYBOT_EXPRESSION_SOURCE_OPENING: return "conversation_start"; - case MYBOT_EXPRESSION_SOURCE_MCP: - return "mcp"; - case MYBOT_EXPRESSION_SOURCE_LOCAL: - return "local"; default: return "state"; } diff --git a/components/mybot_stack/mybot_sdk/CMakeLists.txt b/components/mybot_stack/mybot_sdk/CMakeLists.txt index 990d465..e2a26e1 100644 --- a/components/mybot_stack/mybot_sdk/CMakeLists.txt +++ b/components/mybot_stack/mybot_sdk/CMakeLists.txt @@ -48,9 +48,11 @@ set(MYBOT_SOURCES "${MYBOT_ROOT}/src/platform/mybot_wifi.c" "${MYBOT_ROOT}/src/rtc/mybot_agora_rtc.c" "${MYBOT_ROOT}/src/service/mybot_device_client.c" + "${MYBOT_ROOT}/src/support/mybot_http_header.c" "${MYBOT_ROOT}/src/support/mybot_http_client.c" "${MYBOT_ROOT}/src/support/mybot_json.c" "${MYBOT_ROOT}/src/support/mybot_ringbuf.c" + "${MYBOT_ROOT}/src/support/mybot_url.c" ) idf_component_register( diff --git a/components/mybot_stack/mybot_sdk/mybot/CHANGELOG.md b/components/mybot_stack/mybot_sdk/mybot/CHANGELOG.md index 56e47e4..ba02a91 100644 --- a/components/mybot_stack/mybot_sdk/mybot/CHANGELOG.md +++ b/components/mybot_stack/mybot_sdk/mybot/CHANGELOG.md @@ -12,6 +12,22 @@ This project follows Semantic Versioning. ### Changed - Refresh the Chinese and English pairing-code prompt and digit audio. +- Remove stale external-platform, footprint, endpoint, and licensing details from the guides, and + document only the device-service fields consumed by this repository. +- Use one bounded URL parser for startup configuration and HTTP requests, and one strict printable + header-value validator for request headers and device authorization credentials. + +### Removed + +- Remove the unused outbound RTM publish path, including its message-state API, send-result event, + and test-only login/logout wrappers. RTM remains internal to the conversation join lifecycle. +- Remove test-only ring-buffer clear and LCD screen helpers, plus unreachable media mute and LCD + emotion paths that had no production command or key trigger. +- Remove an unused HTTP URL limit, an unreachable RTC state, the redundant Linux OpenSSL build + switch, and the incomplete pkg-config installation. The CMake package remains the supported + installed integration. +- Remove vendored Agora RTSA examples, skills, demo/test media, helper binaries, and duplicate build + metadata. Keep only the Linux public header, `.config`, shared library, and package provenance. ## [1.3.0] - 2026-10-19 diff --git a/components/mybot_stack/mybot_sdk/mybot/THIRD_PARTY_NOTICES.md b/components/mybot_stack/mybot_sdk/mybot/THIRD_PARTY_NOTICES.md index f12545e..3a7cc31 100644 --- a/components/mybot_stack/mybot_sdk/mybot/THIRD_PARTY_NOTICES.md +++ b/components/mybot_stack/mybot_sdk/mybot/THIRD_PARTY_NOTICES.md @@ -1,36 +1,46 @@ # Third-party notices -The [SDK Apache-2.0 license](LICENSE) applies to code maintained by agent-studio-device-firmware -unless a file states otherwise. It does not replace third-party terms. This file is informational, -not legal advice. +The root Apache-2.0 license applies to project-maintained code unless a file states otherwise. It does +not replace third-party terms. This file is informational, not legal advice. ## AOSL -Location: [components/mybot_stack/aosl](../../aosl) — bundled sources pinned to upstream commit +Location: `third_party/aosl` — a git submodule pinned to upstream commit `84e086084ebcd0ae2455a0ce5721950c5fe2e656` of https://github.com/AgoraIO-Community/aosl. -AOSL includes its [LICENSE](../../aosl/LICENSE), which is based on Apache-2.0 and adds restrictive +AOSL includes `third_party/aosl/LICENSE`, which is based on Apache-2.0 and adds restrictive conditions. Read that file before using, modifying, deploying, or redistributing AOSL. Do not label the combined repository or binary as uniformly Apache-2.0. -The ESP32 firmware repository includes these sources directly. See its -[release guide](../../../../docs/RELEASING.md) for dependency and artifact checks. +GitHub's automatic source archives omit AOSL. After a Git clone, initialize it with +`git submodule update --init --recursive`; this command cannot populate an archive without `.git`. +The source asset produced by `scripts/release.sh package TAG` includes the tag's pinned AOSL +contents and license. See [the release guide](../../../../docs/RELEASING.md) for archive usage. ## Agora RTSA SDK -Location: [components/mybot_stack/agora_rtc](../../agora_rtc). This firmware uses the -ESP32-S3 static RTSA Lite package, v1.10.1, build 1270872 (`20260828_194128`), recorded in -[dependency baselines](../../../../VENDORED_SOURCES.md). +Location: `third_party/agora_rtsa_sdk`. The bundled shared-library package identifies itself as +`Agora-RTSALite-RmRcAcAj-x86_64-linux-gnu-v1.10.1-20260828_180234-1270765`. It is provided for +Linux **development and demo** use only and is intentionally retained in this repository for the +Linux reference demo (it is not removed). -No standalone license or NOTICE for the bundled RTSA binary was found in the supplied package. -Possession of the files is not evidence of redistribution rights. Commercial or +The vendored package retains only `PACKAGE_INFO`, the public API header, `.config`, and the +shared library. Vendor examples, skills, demo/test assets, and helper binaries are not part of this +repository. + +Package provenance recorded for this update: + +- Source archive: `Agora-RTSALite-RmRcAcAj-x86_64-linux-gnu-v1.10.1-20260828_180234-1270765.tgz` +- Archive SHA-256: `739901d09a4161a33f36e06281fe30dc11629f1f3271e55a5662501593985fbf` +- `libagora-rtc-sdk.so` SHA-256: `269d985f2fcb86ce259591853e59bc5a5d86f5f8fa82a1408bc7ac3795c3f999` + +No standalone license or NOTICE for the bundled RTSA binary was found in the package during the +1.1.0 audit. Possession of the files is not evidence of redistribution rights. Commercial or production use and redistribution (source archives, binaries, container/firmware images, mirrors) require a separate license from Agora (声网). Release maintainers must retain the applicable terms and written redistribution authorization in the release records before publishing an artifact that contains the binary; the presence of this repository copy does not itself record that authorization. -File-specific copyright and license headers also remain in force. - ## cJSON-derived implementation `src/support/mybot_json.c` and `src/internal/mybot_json.h` are namespaced derivatives of cJSON. @@ -40,5 +50,5 @@ They retain the MIT license and Dave Gamble copyright notice in the source. Publish a release artifact containing the bundled Agora binary only after its license and written redistribution authorization have been verified and retained in the release records. If that record -is unavailable, exclude the binary and require users to supply an authorized package, as described -in the firmware's [third-party notices](../../../../THIRD_PARTY_NOTICES.md#agora-rtsa). +is unavailable, exclude the binary and require users to supply `AGORA_SDK_DIR` and +`AGORA_RTC_LIBRARY` locally. diff --git a/components/mybot_stack/mybot_sdk/mybot/include/mybot/platform/mybot_lcd.h b/components/mybot_stack/mybot_sdk/mybot/include/mybot/platform/mybot_lcd.h index 7598216..c29a9fe 100644 --- a/components/mybot_stack/mybot_sdk/mybot/include/mybot/platform/mybot_lcd.h +++ b/components/mybot_stack/mybot_sdk/mybot/include/mybot/platform/mybot_lcd.h @@ -25,8 +25,7 @@ extern "C" { * * Indicators are represented as a bitmask in mybot_lcd_content_t. Platforms * should ignore bits they do not recognize and must not change the base screen - * layout when no supported indicator is set. Server states are mutually exclusive; - * emotions are mutually exclusive, one-shot expression commands. + * layout when no supported indicator is set. Server states are mutually exclusive. */ typedef enum { /** No additional indicator. */ @@ -39,14 +38,6 @@ typedef enum { MYBOT_LCD_INDICATOR_THINKING = 1u << 2, /** The server is speaking to the user. */ MYBOT_LCD_INDICATOR_SPEAKING = 1u << 3, - /** Display a happy expression. */ - MYBOT_LCD_INDICATOR_HAPPY = 1u << 4, - /** Display a sad expression. */ - MYBOT_LCD_INDICATOR_SAD = 1u << 5, - /** Display an angry expression. */ - MYBOT_LCD_INDICATOR_ANGRY = 1u << 6, - /** Display a surprised expression. */ - MYBOT_LCD_INDICATOR_SURPRISED = 1u << 7, } mybot_lcd_indicator_t; /** @@ -55,13 +46,6 @@ typedef enum { #define MYBOT_LCD_INDICATOR_SERVER_STATE_MASK \ (MYBOT_LCD_INDICATOR_LISTENING | MYBOT_LCD_INDICATOR_THINKING | MYBOT_LCD_INDICATOR_SPEAKING) -/** - * Mask of the mutually exclusive, one-shot emotion indicators. - */ -#define MYBOT_LCD_INDICATOR_EMOTION_MASK \ - (MYBOT_LCD_INDICATOR_HAPPY | MYBOT_LCD_INDICATOR_SAD | MYBOT_LCD_INDICATOR_ANGRY | \ - MYBOT_LCD_INDICATOR_SURPRISED) - /** * Workflow screens rendered by the SDK. * @@ -109,10 +93,6 @@ typedef struct { * Other screens should * normally be rendered with MYBOT_LCD_INDICATOR_NONE. The listening, * thinking and speaking bits are mutually exclusive server-state overlays. - * Each render call containing an emotion bit triggers a new expression, - * including consecutive calls with the same bit. - * Ordinary renders without an emotion bit update the retained overlays and - * must not restart or cancel the platform's current expression. * * @note The field is appended to the 1.1.0 content structure. Build the * SDK and platform LCD adapter against the same public header. @@ -143,12 +123,6 @@ typedef struct { /** * Render one workflow screen. * - * Submit emotion commands quickly; expression duration and animation timing - * belong to the platform. A new emotion replaces the unfinished expression. - * Rendering a screen other than MYBOT_LCD_SCREEN_IN_CONVERSATION must cancel - * any current expression. The SDK does not retry a failed emotion render or - * replay it on a later ordinary render. - * * @param ctx LCD implementation context from init() * @param content semantic screen content; borrowed for the duration of * the call diff --git a/components/mybot_stack/mybot_sdk/mybot/src/core/mybot_app.c b/components/mybot_stack/mybot_sdk/mybot/src/core/mybot_app.c index b3192f1..efdc377 100644 --- a/components/mybot_stack/mybot_sdk/mybot/src/core/mybot_app.c +++ b/components/mybot_stack/mybot_sdk/mybot/src/core/mybot_app.c @@ -13,6 +13,7 @@ #include "mybot_platform_registry.h" #include "mybot_json.h" #include "mybot_state_model.h" +#include "mybot_url.h" #include "mybot_video_internal.h" #include "mybot_wifi_internal.h" @@ -1088,58 +1089,8 @@ static void on_wifi_event(mybot_wifi_event_t event, void *user_data) { } static bool server_url_is_valid(const char *url) { - if (!url) { - return false; - } - const char *p = NULL; -#if MYBOT_ENABLE_HTTPS - if (strncmp(url, "https://", 8) == 0) { - p = url + 8; - } -#endif -#if MYBOT_ALLOW_INSECURE_HTTP - if (!p && strncmp(url, "http://", 7) == 0) { - p = url + 7; - } -#endif - if (!p || !p[0]) { - return false; - } - const char *host = p; - while (*p && *p != ':' && *p != '/') { - unsigned char c = (unsigned char)*p; - if (c <= 0x20 || c > 0x7e || c == '@' || c == '?' || c == '#') { - return false; - } - ++p; - } - if (p == host) { - return false; - } - if (*p == ':') { - ++p; - if (!(*p >= '0' && *p <= '9')) { - return false; - } - unsigned long port = 0; - while (*p >= '0' && *p <= '9') { - port = port * 10U + (unsigned long)(*p - '0'); - if (port > 65535U) { - return false; - } - ++p; - } - if (port == 0) { - return false; - } - } - for (; *p; ++p) { - unsigned char c = (unsigned char)*p; - if (c <= 0x20 || c > 0x7e || c == '\\' || c == '#') { - return false; - } - } - return true; + mybot_url_parts_t parts; + return mybot_url_parse(url, &parts) == 0; } static bool config_is_valid(const mybot_config_t *cfg) { diff --git a/components/mybot_stack/mybot_sdk/mybot/src/core/mybot_presenter.c b/components/mybot_stack/mybot_sdk/mybot/src/core/mybot_presenter.c index a1981bc..9055512 100644 --- a/components/mybot_stack/mybot_sdk/mybot/src/core/mybot_presenter.c +++ b/components/mybot_stack/mybot_sdk/mybot/src/core/mybot_presenter.c @@ -93,25 +93,6 @@ void mybot_presenter_clear_server_indicators(mybot_presenter_t *presenter) { } } -int mybot_presenter_show_emotion(mybot_presenter_t *presenter, mybot_lcd_indicator_t indicator) { - if (!presenter || !presenter->active || - (indicator != MYBOT_LCD_INDICATOR_HAPPY && indicator != MYBOT_LCD_INDICATOR_SAD && - indicator != MYBOT_LCD_INDICATOR_ANGRY && indicator != MYBOT_LCD_INDICATOR_SURPRISED)) { - AOSL_LOG_WRN("cannot render LCD emotion: invalid parameters or inactive display"); - return -1; - } - - mybot_lcd_content_t content; - memset(&content, 0, sizeof(content)); - content.screen = MYBOT_LCD_SCREEN_IN_CONVERSATION; - content.indicators = presenter->indicators | indicator; - int ret = mybot_lcd_show_content(&presenter->lcd, &content); - if (ret < 0) { - AOSL_LOG_WRN("failed to render LCD emotion %u", (unsigned)indicator); - } - return ret; -} - static bool app_state_matches_device_state(mybot_device_state_t device_state, mybot_state_t app_state) { switch (device_state) { diff --git a/components/mybot_stack/mybot_sdk/mybot/src/internal/mybot_agora_rtc.h b/components/mybot_stack/mybot_sdk/mybot/src/internal/mybot_agora_rtc.h index f02145d..6e464a7 100644 --- a/components/mybot_stack/mybot_sdk/mybot/src/internal/mybot_agora_rtc.h +++ b/components/mybot_stack/mybot_sdk/mybot/src/internal/mybot_agora_rtc.h @@ -21,7 +21,6 @@ typedef enum { MYBOT_RTC_STATE_RECONNECTING, MYBOT_RTC_STATE_DISCONNECTED, MYBOT_RTC_STATE_ERROR, - MYBOT_RTC_STATE_INIT_FAILED, } mybot_rtc_state_t; /** RTM lifecycle events forwarded from the Agora SDK. */ @@ -31,23 +30,11 @@ typedef enum { MYBOT_RTM_EVENT_EXIT = 2, } mybot_rtm_event_type_t; -/** RTM delivery state forwarded by the Agora SDK. */ -typedef enum { - MYBOT_RTM_MSG_STATE_INIT = 0, - MYBOT_RTM_MSG_STATE_RECEIVED, - MYBOT_RTM_MSG_STATE_UNREACHABLE, - MYBOT_RTM_MSG_STATE_TIMEOUT, -} mybot_rtm_message_state_t; - /** Maximum byte capacity of an RTM account including its terminating NUL. */ #define MYBOT_RTM_UID_MAX_LEN 64 -/* Agora RTSA is process-wide and supports one active 1-to-1 conversation. - * A dedicated RTC MPQ owns all mutable state and serializes lifecycle and - * media operations. Vendor callbacks are copied and queued to that worker; - * application callbacks must not re-enter this API. Only connection-scoped - * events update call state; RTSA global errors are logged without being - * forwarded. */ +/* rtc_mpq owns all mutable state. Vendor payloads are copied before dispatch; + * application callbacks must not re-enter this API. */ typedef struct { void (*on_remote_audio)(uint32_t uid, const void *data, size_t len, void *user_data); void (*on_token_will_expire)(void *user_data); @@ -59,8 +46,6 @@ typedef struct { void (*on_rtm_subscribe_result)(const char *channel, int error_code, void *user_data); void (*on_rtm_subscribe_data)(const char *channel, const char *rtm_uid, const void *data, size_t len, const char *custom_type, void *user_data); - void (*on_rtm_send_data_result)(const char *rtm_uid, uint32_t msg_id, - mybot_rtm_message_state_t state, void *user_data); #if MYBOT_ENABLE_VIDEO void (*on_video_key_frame_requested)(void *user_data); void (*on_video_target_bitrate_changed)(uint32_t target_bps, void *user_data); @@ -68,10 +53,7 @@ typedef struct { void *user_data; } mybot_agora_rtc_callbacks_t; -/** Initialize the process-wide RTSA service once for the current mybot run. - * Repeated calls are accepted only after a successful initialization with - * the same App ID and while no conversation is active. All state and vendor - * calls are serialized by a dedicated RTC MPQ worker. */ +/** Initialize the process-wide RTSA service on rtc_mpq. */ int mybot_agora_rtc_init(const char *app_id, const mybot_agora_rtc_callbacks_t *callbacks); /** @@ -85,19 +67,6 @@ int mybot_agora_rtc_init(const char *app_id, const mybot_agora_rtc_callbacks_t * */ bool mybot_agora_rtc_rtm_uid_is_valid(const char *rtm_uid); -/** Log in to RTM using the server-issued local RTC UID and RTM token. */ -int mybot_agora_rtc_login_rtm(const char *rtm_uid, const char *rtm_token); - -/** Log out of an explicitly requested RTM session. Join-owned sessions are logged out by leave. */ -int mybot_agora_rtc_logout_rtm(void); - -/** Send one point-to-point RTM message after the login event succeeds. */ -int mybot_agora_rtc_send_rtm_data(const char *peer_rtm_uid, const void *data, size_t len, - uint32_t msg_id, const char *custom_type); - -/** Return whether the RTM login event has completed successfully. */ -bool mybot_agora_rtc_is_rtm_logged_in(void); - /** Create a connection and start joining one 1-to-1 channel. RTM login is * requested first using user_account as the local RTM UID and token as the RTM * token. After RTM login succeeds, this subscribes to the RTM channel with the diff --git a/components/mybot_stack/mybot_sdk/mybot/src/internal/mybot_announce_internal.h b/components/mybot_stack/mybot_sdk/mybot/src/internal/mybot_announce_internal.h index 125a4fe..5c94252 100644 --- a/components/mybot_stack/mybot_sdk/mybot/src/internal/mybot_announce_internal.h +++ b/components/mybot_stack/mybot_sdk/mybot/src/internal/mybot_announce_internal.h @@ -27,16 +27,7 @@ typedef struct { uint32_t generation; } mybot_announce_t; -/* - * SDK-internal announcement facade. - * - * The public mybot/platform/mybot_announce.h only exposes the platform contract - * (ops table + mybot_platform_register()); the SDK core drives the registered - * implementation through the functions below. When a pair code is obtained the core - * queues the fixed prompt followed by one sound per digit. The playback worker - * streams those sounds directly to the normal speaker path without mixing them - * into the RTC playback ring. - */ +/* Playback reads source sounds under lock; the playback worker owns PCM delivery. */ /** Initialize the registered implementation. No-op when none is registered. */ int mybot_announce_init(mybot_announce_t *announce); @@ -44,14 +35,7 @@ int mybot_announce_init(mybot_announce_t *announce); /** Release the implementation and any queued announcement. Idempotent. */ void mybot_announce_deinit(mybot_announce_t *announce); -/** - * Start the pairing-code announcement: fixed prompt + one sound per digit. - * - * @param code pair code from the device service - * @return 0 when playback was queued, -1 when the feature is disabled or the - * prompt asset is unavailable. A failed replacement preserves the - * previous announcement. - */ +/** Queue a pair-code announcement. A failed replacement preserves the current one. */ int mybot_announce_play_pair_code(mybot_announce_t *announce, const char *code); /** Discard source sounds and invalidate PCM buffered by the playback worker. */ diff --git a/components/mybot_stack/mybot_sdk/mybot/src/internal/mybot_audio_internal.h b/components/mybot_stack/mybot_sdk/mybot/src/internal/mybot_audio_internal.h index 83bec8d..e5c02cd 100644 --- a/components/mybot_stack/mybot_sdk/mybot/src/internal/mybot_audio_internal.h +++ b/components/mybot_stack/mybot_sdk/mybot/src/internal/mybot_audio_internal.h @@ -20,12 +20,7 @@ typedef struct { aosl_atomic_t media_volume; } mybot_audio_t; -/** - * SDK-internal audio facade. The public mybot/platform/mybot_audio.h only - * exposes the platform contract (ops tables + registration); volume control is - * SDK-internal: a registered device volume implementation is the primary path, - * and the media-volume software gain is the fallback when no implementation is active. - */ +/* Platform PCM and volume contracts are defined in . */ /** Snapshot the default registered implementations into a runtime context. */ void mybot_audio_context_init(mybot_audio_t *audio); @@ -39,34 +34,13 @@ void mybot_audio_device_volume_deinit(mybot_audio_t *audio); /** Return whether the registered device volume implementation is initialized and active. */ bool mybot_audio_device_volume_is_active(const mybot_audio_t *audio); -/** - * Set the real device volume through the active implementation. - * - * @param volume 0 (mute) .. MYBOT_AUDIO_VOLUME_MAX (full scale) - * @return 0 on success, -1 if the implementation is unavailable or volume is invalid - */ +/** Set device volume through the active implementation. */ int mybot_audio_device_set_volume(mybot_audio_t *audio, int volume); -/** - * Get the current real device volume. - * - * Reads the implementation when it provides get_volume(); otherwise returns the - * SDK-tracked last value. Succeeds only while the implementation is active. - * - * @param volume [out] current real device volume - * @return 0 on success, -1 if the implementation is unavailable or volume is NULL - */ +/** Read the current device volume, or the last SDK-tracked value if unsupported. */ int mybot_audio_device_get_volume(mybot_audio_t *audio, int *volume); -/** - * Set the fallback media volume. - * - * Stored as a 0..100 software gain applied to downlink PCM only when no - * device volume implementation is active. Volume 100 is unity gain. - * - * @param volume 0 (mute) .. MYBOT_AUDIO_VOLUME_MAX (full scale) - * @return 0 on success, -1 on invalid volume - */ +/** Set the fallback downlink software gain. */ int mybot_audio_set_media_volume(mybot_audio_t *audio, int volume); /** Get the fallback media volume setting (defaults to MYBOT_AUDIO_VOLUME_DEFAULT). */ diff --git a/components/mybot_stack/mybot_sdk/mybot/src/internal/mybot_device_lifecycle.h b/components/mybot_stack/mybot_sdk/mybot/src/internal/mybot_device_lifecycle.h index f084a7b..ddecb3d 100644 --- a/components/mybot_stack/mybot_sdk/mybot/src/internal/mybot_device_lifecycle.h +++ b/components/mybot_stack/mybot_sdk/mybot/src/internal/mybot_device_lifecycle.h @@ -109,20 +109,7 @@ typedef struct { aosl_atomic_t network_generation; } mybot_device_lifecycle_t; -/* ---------------------------------------------------------- - * API - * ---------------------------------------------------------- */ - -/** Initialize the device state machine. - * @param lifecycle caller-owned lifecycle context - * @param kv_store initialized credential store for this runtime - * @param server_base Device-service base URL. - * @param device_id Unique device identifier (e.g. "AG-A1B2C3") - * @param firmware_ver Firmware version string (may be NULL) - * @param hw_model Hardware model string (may be NULL) - * @param cbs Callbacks (may be NULL) - * @return 0 on success, -1 on error. - */ +/** Initialize a caller-owned lifecycle. Returns 0 on success, -1 on error. */ int mybot_device_lifecycle_init(mybot_device_lifecycle_t *lifecycle, mybot_kv_store_t *kv_store, const char *server_base, const char *device_id, const char *firmware_ver, const char *hw_model, @@ -137,11 +124,7 @@ void mybot_device_lifecycle_tick(mybot_device_lifecycle_t *lifecycle); void mybot_device_lifecycle_service_result(mybot_device_lifecycle_t *lifecycle, const mybot_device_service_request_t *request); -/** - * Notify the state machine whether device-service networking is available. - * May be called from any thread as an atomic network input. While offline, tick() - * performs no HTTP actions; the control owner ends an active conversation locally. - */ +/** Publish an atomic network snapshot from any thread; tick() consumes it on control. */ void mybot_device_lifecycle_set_network_available(mybot_device_lifecycle_t *lifecycle, bool available); @@ -149,13 +132,15 @@ void mybot_device_lifecycle_set_network_available(mybot_device_lifecycle_t *life * Must be called by the application control owner. */ void mybot_device_lifecycle_shutdown(mybot_device_lifecycle_t *lifecycle); -/** Request a fresh pairing flow from the application control owner. */ +/* Pair, start, and stop requests must be serialized by the application control owner. */ + +/** Request a fresh pairing flow. */ void mybot_device_lifecycle_request_pair(mybot_device_lifecycle_t *lifecycle); -/** Trigger conversation start from the application control owner. */ +/** Trigger conversation start. */ void mybot_device_lifecycle_request_start(mybot_device_lifecycle_t *lifecycle); -/** Trigger conversation stop from the application control owner. */ +/** Trigger conversation stop. */ void mybot_device_lifecycle_request_stop(mybot_device_lifecycle_t *lifecycle); /** Publish from an RTC callback that the active connection ended. */ diff --git a/components/mybot_stack/mybot_sdk/mybot/src/internal/mybot_http_client.h b/components/mybot_stack/mybot_sdk/mybot/src/internal/mybot_http_client.h index 192b380..d9c1290 100644 --- a/components/mybot_stack/mybot_sdk/mybot/src/internal/mybot_http_client.h +++ b/components/mybot_stack/mybot_sdk/mybot/src/internal/mybot_http_client.h @@ -2,6 +2,7 @@ #ifndef MYBOT_HTTP_CLIENT_H_ #define MYBOT_HTTP_CLIENT_H_ +#include #include #ifdef __cplusplus @@ -16,6 +17,10 @@ typedef struct { size_t body_len; /* body length in bytes */ } mybot_http_client_response_t; +/** Validate a printable HTTP header value. Embedded controls are rejected; + * horizontal tabs are accepted only when allow_tab is true. */ +bool mybot_http_header_value_is_safe(const char *value, bool allow_tab); + /** * @brief HTTP GET with extra custom headers. * @param extra_headers Additional header lines to append (e.g. diff --git a/components/mybot_stack/mybot_sdk/mybot/src/internal/mybot_key_internal.h b/components/mybot_stack/mybot_sdk/mybot/src/internal/mybot_key_internal.h index 4fa4563..9036d7e 100644 --- a/components/mybot_stack/mybot_sdk/mybot/src/internal/mybot_key_internal.h +++ b/components/mybot_stack/mybot_sdk/mybot/src/internal/mybot_key_internal.h @@ -16,12 +16,6 @@ typedef struct { bool active; } mybot_key_t; -/** - * SDK-internal key facade. The public mybot/platform/mybot_key.h only exposes - * the platform contract (event enum, handler typedef, ops table and - * mybot_platform_register()); the SDK core manages the key implementation lifecycle. - */ - /** Initialize the registered implementation and install the application event handler. */ int mybot_key_init(mybot_key_t *key, mybot_key_event_handler_t handler, void *user_data); diff --git a/components/mybot_stack/mybot_sdk/mybot/src/internal/mybot_kv_store_internal.h b/components/mybot_stack/mybot_sdk/mybot/src/internal/mybot_kv_store_internal.h index 97fea4d..1dd4acd 100644 --- a/components/mybot_stack/mybot_sdk/mybot/src/internal/mybot_kv_store_internal.h +++ b/components/mybot_stack/mybot_sdk/mybot/src/internal/mybot_kv_store_internal.h @@ -13,13 +13,6 @@ typedef struct { void *ctx; } mybot_kv_store_t; -/** - * SDK-internal KV-store facade. The public mybot/platform/mybot_kv_store.h - * only exposes the platform contract (ops table + mybot_platform_register()); - * the SDK core uses the storage operations below, e.g. to persist device - * credentials. Application code has no documented access to this store. - */ - int mybot_kv_store_init(mybot_kv_store_t *store); void mybot_kv_store_deinit(mybot_kv_store_t *store); int mybot_kv_store_get(mybot_kv_store_t *store, const char *key, void *value, size_t capacity, diff --git a/components/mybot_stack/mybot_sdk/mybot/src/internal/mybot_lcd_internal.h b/components/mybot_stack/mybot_sdk/mybot/src/internal/mybot_lcd_internal.h index 5a80d72..aed54c4 100644 --- a/components/mybot_stack/mybot_sdk/mybot/src/internal/mybot_lcd_internal.h +++ b/components/mybot_stack/mybot_sdk/mybot/src/internal/mybot_lcd_internal.h @@ -14,12 +14,7 @@ typedef struct { bool active; } mybot_lcd_t; -/** - * SDK-internal LCD facade. The public mybot/platform/mybot_lcd.h only exposes - * the platform contract (ops table + mybot_platform_register()); the SDK core drives - * the registered implementation through the functions below. All calls are serialized by the - * application control owner. - */ +/* All LCD calls are serialized by the application control owner. */ /** Return whether the current platform registered an LCD implementation. */ bool mybot_lcd_is_registered(void); @@ -27,9 +22,6 @@ bool mybot_lcd_is_registered(void); /** Initialize the registered LCD implementation. */ int mybot_lcd_init(mybot_lcd_t *lcd); -/** Render a workflow screen from the control owner. */ -int mybot_lcd_show_screen(mybot_lcd_t *lcd, mybot_lcd_screen_t screen); - /** Render semantic LCD content from the control owner. */ int mybot_lcd_show_content(mybot_lcd_t *lcd, const mybot_lcd_content_t *content); diff --git a/components/mybot_stack/mybot_sdk/mybot/src/internal/mybot_media_pipeline.h b/components/mybot_stack/mybot_sdk/mybot/src/internal/mybot_media_pipeline.h index d57f32f..10b2246 100644 --- a/components/mybot_stack/mybot_sdk/mybot/src/internal/mybot_media_pipeline.h +++ b/components/mybot_stack/mybot_sdk/mybot/src/internal/mybot_media_pipeline.h @@ -48,7 +48,6 @@ typedef struct { bool initialized; aosl_atomic_t running; aosl_atomic_t rtc_connected; - aosl_atomic_t muted; #if MYBOT_WAKE_WORDS aosl_atomic_t wake_words_enabled; #endif @@ -120,12 +119,10 @@ void mybot_media_pipeline_push_remote_audio(mybot_media_pipeline_t *pipeline, co int mybot_media_pipeline_play_prompt(mybot_media_pipeline_t *pipeline, mybot_prompt_type_t type, const void *args); void mybot_media_pipeline_stop_prompt(mybot_media_pipeline_t *pipeline); -/** Set playback volume (0..100) without changing the independent mute setting. */ +/** Set playback volume from 0 to 100. */ int mybot_media_pipeline_set_volume(mybot_media_pipeline_t *pipeline, int volume); /** Adjust playback volume by -100..100, saturating the result to 0..100. */ int mybot_media_pipeline_adjust_volume(mybot_media_pipeline_t *pipeline, int delta); -/** Mute RTC and local prompt output; microphone capture and upload continue unchanged. */ -void mybot_media_pipeline_set_muted(mybot_media_pipeline_t *pipeline, bool muted); #ifdef __cplusplus } diff --git a/components/mybot_stack/mybot_sdk/mybot/src/internal/mybot_presenter.h b/components/mybot_stack/mybot_sdk/mybot/src/internal/mybot_presenter.h index a69048c..96625c9 100644 --- a/components/mybot_stack/mybot_sdk/mybot/src/internal/mybot_presenter.h +++ b/components/mybot_stack/mybot_sdk/mybot/src/internal/mybot_presenter.h @@ -29,8 +29,6 @@ void mybot_presenter_update_server_indicator(mybot_presenter_t *presenter, mybot_lcd_indicator_t indicator, bool active); /** Clear all server-state indicators. */ void mybot_presenter_clear_server_indicators(mybot_presenter_t *presenter); -/** Render one emotion command without retaining or replaying it on ordinary updates. */ -int mybot_presenter_show_emotion(mybot_presenter_t *presenter, mybot_lcd_indicator_t indicator); void mybot_presenter_render_state(mybot_presenter_t *presenter, const mybot_state_model_t *state_model); diff --git a/components/mybot_stack/mybot_sdk/mybot/src/internal/mybot_ringbuf.h b/components/mybot_stack/mybot_sdk/mybot/src/internal/mybot_ringbuf.h index 772bd6a..d68bc30 100644 --- a/components/mybot_stack/mybot_sdk/mybot/src/internal/mybot_ringbuf.h +++ b/components/mybot_stack/mybot_sdk/mybot/src/internal/mybot_ringbuf.h @@ -12,9 +12,9 @@ extern "C" { * @brief Lock-free single-producer single-consumer ring buffer. * * Data access is thread-safe only in SPSC mode (one writer, one reader). - * create(), destroy(), and clear() require external lifecycle synchronization - * and must not overlap data access. Read, write, and size-query operations use - * no locks and are non-blocking. + * create() and destroy() require external lifecycle synchronization and must + * not overlap data access. Read, write, and size-query operations use no locks + * and are non-blocking. * * Memory ordering: the payload is made visible to the peer before the index is * published (release) and the peer observes the published index before touching @@ -30,9 +30,6 @@ mybot_ringbuf_t mybot_ringbuf_create(int size); /** Destroy the ring buffer. */ int mybot_ringbuf_destroy(mybot_ringbuf_t handle); -/** Reset to empty. */ -int mybot_ringbuf_clear(mybot_ringbuf_t handle); - /** Number of free bytes available for writing. */ int mybot_ringbuf_get_free_size(mybot_ringbuf_t handle); diff --git a/components/mybot_stack/mybot_sdk/mybot/src/internal/mybot_url.h b/components/mybot_stack/mybot_sdk/mybot/src/internal/mybot_url.h new file mode 100644 index 0000000..7f298b4 --- /dev/null +++ b/components/mybot_stack/mybot_sdk/mybot/src/internal/mybot_url.h @@ -0,0 +1,40 @@ +/* SPDX-License-Identifier: Apache-2.0 */ +#ifndef MYBOT_URL_H_ +#define MYBOT_URL_H_ + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +#define MYBOT_URL_HOST_CAPACITY 128 +#define MYBOT_URL_PATH_CAPACITY 512 +#define MYBOT_URL_HTTP_PORT 80 +#define MYBOT_URL_HTTPS_PORT 443 + +typedef struct { + bool use_tls; + char host[MYBOT_URL_HOST_CAPACITY]; + int port; + char path[MYBOT_URL_PATH_CAPACITY]; +} mybot_url_parts_t; + +/** + * Parse an absolute HTTP(S) URL into bounded components. + * + * HTTPS is accepted when MYBOT_ENABLE_HTTPS is enabled. Plain HTTP is accepted + * only when MYBOT_ALLOW_INSECURE_HTTP is explicitly enabled. The host must be a + * non-empty ASCII DNS name or address without userinfo; the port must be + * 1..65535 and the path/query must be a printable request target without a + * fragment or backslash. + * + * @return 0 on success, -1 on malformed or disabled URL forms. + */ +int mybot_url_parse(const char *url, mybot_url_parts_t *parts); + +#ifdef __cplusplus +} +#endif + +#endif /* MYBOT_URL_H_ */ diff --git a/components/mybot_stack/mybot_sdk/mybot/src/internal/mybot_wake_words_internal.h b/components/mybot_stack/mybot_sdk/mybot/src/internal/mybot_wake_words_internal.h index 90b85c4..e5b0f26 100644 --- a/components/mybot_stack/mybot_sdk/mybot/src/internal/mybot_wake_words_internal.h +++ b/components/mybot_stack/mybot_sdk/mybot/src/internal/mybot_wake_words_internal.h @@ -14,13 +14,6 @@ typedef struct { bool active; } mybot_wake_words_t; -/** - * SDK-internal wake-word facade. The public mybot/platform/mybot_wake_words.h - * only exposes the platform contract (handler typedef, ops table and - * mybot_platform_register()); the SDK audio pipeline drives the registered - * implementation through the functions below. - */ - /** Initialize the registered implementation for the capture PCM format. */ int mybot_wake_words_init(mybot_wake_words_t *wake_words, int sample_rate, int channels, int bits_per_sample, mybot_wake_words_handler_t handler, void *user_data); diff --git a/components/mybot_stack/mybot_sdk/mybot/src/internal/mybot_wifi_internal.h b/components/mybot_stack/mybot_sdk/mybot/src/internal/mybot_wifi_internal.h index 7bb8e54..0a0a128 100644 --- a/components/mybot_stack/mybot_sdk/mybot/src/internal/mybot_wifi_internal.h +++ b/components/mybot_stack/mybot_sdk/mybot/src/internal/mybot_wifi_internal.h @@ -16,13 +16,6 @@ typedef struct { bool active; } mybot_wifi_t; -/** - * SDK-internal Wi-Fi facade. The public mybot/platform/mybot_wifi.h only - * exposes the platform contract (event and handler types, ops table and - * mybot_platform_register()); the SDK consumes connectivity events, while the - * product owns provisioning and network credentials. - */ - /** * Register the platform connectivity monitor. Initial usable connectivity and * subsequent transitions are reported through handler. diff --git a/components/mybot_stack/mybot_sdk/mybot/src/media/mybot_media_pipeline.c b/components/mybot_stack/mybot_sdk/mybot/src/media/mybot_media_pipeline.c index 812820f..ca19ba3 100644 --- a/components/mybot_stack/mybot_sdk/mybot/src/media/mybot_media_pipeline.c +++ b/components/mybot_stack/mybot_sdk/mybot/src/media/mybot_media_pipeline.c @@ -196,12 +196,9 @@ static void playback_timer(aosl_timer_t id, const aosl_ts_t *now, uintptr_t argc return; } const int16_t *write_data = pipeline->pb_pending + pipeline->pb_pending_offset; - if (aosl_atomic_read(&pipeline->muted)) { - memset(pipeline->announce_frame, 0, (size_t)pipeline->pb_pending_frames * frame_bytes); - write_data = pipeline->announce_frame; - } else if (!mybot_audio_device_volume_is_active(&pipeline->audio) && - mybot_audio_get_media_volume(&pipeline->audio) != MYBOT_AUDIO_VOLUME_MAX) { - /* Keep the pending PCM unchanged so retries use the latest volume and mute setting. */ + if (!mybot_audio_device_volume_is_active(&pipeline->audio) && + mybot_audio_get_media_volume(&pipeline->audio) != MYBOT_AUDIO_VOLUME_MAX) { + /* Keep the pending PCM unchanged so retries use the latest volume. */ memcpy(pipeline->announce_frame, write_data, (size_t)pipeline->pb_pending_frames * frame_bytes); mybot_audio_apply_media_volume(&pipeline->audio, pipeline->announce_frame, @@ -372,7 +369,6 @@ int mybot_media_pipeline_start(mybot_media_pipeline_t *pipeline, pipeline->cbs = *callbacks; pipeline->stop_complete = false; mybot_audio_context_init(&pipeline->audio); - aosl_atomic_set(&pipeline->muted, false); aosl_atomic_set(&pipeline->running, true); const mybot_audio_capture_ops_t *cap_ops = pipeline->audio.capture_ops; @@ -675,9 +671,3 @@ int mybot_media_pipeline_adjust_volume(mybot_media_pipeline_t *pipeline, int del } return mybot_media_pipeline_set_volume(pipeline, volume); } - -void mybot_media_pipeline_set_muted(mybot_media_pipeline_t *pipeline, bool muted) { - if (pipeline) { - aosl_atomic_set(&pipeline->muted, muted); - } -} diff --git a/components/mybot_stack/mybot_sdk/mybot/src/platform/mybot_lcd.c b/components/mybot_stack/mybot_sdk/mybot/src/platform/mybot_lcd.c index a0b1097..a5da9ca 100644 --- a/components/mybot_stack/mybot_sdk/mybot/src/platform/mybot_lcd.c +++ b/components/mybot_stack/mybot_sdk/mybot/src/platform/mybot_lcd.c @@ -47,17 +47,6 @@ int mybot_lcd_init(mybot_lcd_t *lcd) { return 0; } -int mybot_lcd_show_screen(mybot_lcd_t *lcd, mybot_lcd_screen_t screen) { - if (!screen_is_valid(screen) || screen == MYBOT_LCD_SCREEN_PAIR_CODE) { - return -1; - } - - mybot_lcd_content_t content; - memset(&content, 0, sizeof(content)); - content.screen = screen; - return mybot_lcd_show_content(lcd, &content); -} - int mybot_lcd_show_content(mybot_lcd_t *lcd, const mybot_lcd_content_t *content) { if (!content) { return -1; diff --git a/components/mybot_stack/mybot_sdk/mybot/src/rtc/mybot_agora_rtc.c b/components/mybot_stack/mybot_sdk/mybot/src/rtc/mybot_agora_rtc.c index 720ca3b..ed36401 100644 --- a/components/mybot_stack/mybot_sdk/mybot/src/rtc/mybot_agora_rtc.c +++ b/components/mybot_stack/mybot_sdk/mybot/src/rtc/mybot_agora_rtc.c @@ -41,12 +41,10 @@ typedef struct { char rtm_uid[MYBOT_RTM_UID_MAX_LEN]; char rtm_channel[AGORA_RTC_CHANNEL_NAME_MAX_LEN + 1]; bool rtm_login_requested; - bool rtm_login_completed; bool rtm_logged_in; bool rtm_subscribe_requested; bool rtm_subscribe_completed; bool rtm_subscribed; - bool rtm_owned_by_join; uint32_t rtm_login_generation; uint32_t rtm_subscribe_generation; } mybot_agora_rtc_t; @@ -87,7 +85,6 @@ static void process_rtm_data(const char *, const void *, size_t, rtm_message_typ static void process_rtm_subscribe_result(const char *, rtm_err_code_e, uint32_t); static void process_rtm_subscribe_data(const char *, const char *, const void *, size_t, rtm_message_type_e, const char *, uint32_t); -static void process_rtm_send_data_result(const char *, uint32_t, rtm_msg_state_e, uint32_t); static void process_join_channel_success(connection_id_t, uint32_t, int); static void process_reconnecting(connection_id_t); static void process_connection_lost(connection_id_t); @@ -108,7 +105,6 @@ static void on_rtm_data(const char *, const void *, size_t, rtm_message_type_e, static void on_rtm_subscribe_result(const char *, rtm_err_code_e); static void on_rtm_subscribe_data(const char *, const char *, const void *, size_t, rtm_message_type_e, const char *); -static void on_rtm_send_data_result(const char *, uint32_t, rtm_msg_state_e); static void on_join_channel_success(connection_id_t, uint32_t, int); static void on_reconnecting(connection_id_t); static void on_connection_lost(connection_id_t); @@ -130,7 +126,6 @@ typedef enum { RTC_EVENT_RTM_DATA, RTC_EVENT_RTM_SUB_RESULT, RTC_EVENT_RTM_SUB_DATA, - RTC_EVENT_RTM_SEND_RESULT, RTC_EVENT_JOIN_SUCCESS, RTC_EVENT_RECONNECTING, RTC_EVENT_CONNECTION_LOST, @@ -177,10 +172,6 @@ typedef struct { char uid_text[MYBOT_RTM_UID_MAX_LEN]; char custom_type[33]; } rtm_sub_data; - struct { - rtm_msg_state_e state; - char uid_text[MYBOT_RTM_UID_MAX_LEN]; - } rtm_send_result; struct { user_info_t user; } user; @@ -249,10 +240,6 @@ static void rtc_event_process(const aosl_ts_t *ts, aosl_refobj_t ref, uintptr_t e->payload.rtm_sub_data.custom_type[0] ? e->payload.rtm_sub_data.custom_type : NULL, e->generation); break; - case RTC_EVENT_RTM_SEND_RESULT: - process_rtm_send_data_result(e->payload.rtm_send_result.uid_text, e->uid, - e->payload.rtm_send_result.state, e->generation); - break; case RTC_EVENT_JOIN_SUCCESS: process_join_channel_success(e->conn_id, e->uid, e->value); break; @@ -358,13 +345,10 @@ static const char *state_name(mybot_rtc_state_t state) { return "DISCONNECTED"; case MYBOT_RTC_STATE_ERROR: return "ERROR"; - case MYBOT_RTC_STATE_INIT_FAILED: - return "INIT_FAILED"; } return "?"; } -/* All state transitions and application callbacks run on the RTC MPQ worker. */ static void set_state(mybot_rtc_state_t state) { if (s_rtc.state == state) { return; @@ -508,7 +492,6 @@ static void process_rtm_event(const char *rtm_uid, rtm_event_type_e event_type, switch (event_type) { case RTM_EVENT_TYPE_LOGIN: callback_gate_lock(); - s_rtc.rtm_login_completed = true; s_rtc.rtm_logged_in = error_code == ERR_RTM_OK; callback_gate_unlock(); if (s_rtc.rtm_logged_in) { @@ -677,16 +660,6 @@ static void process_rtm_subscribe_data(const char *channel, const char *rtm_uid, } } -static void process_rtm_send_data_result(const char *rtm_uid, uint32_t msg_id, - rtm_msg_state_e state, uint32_t generation) { - if (s_rtc.rtm_login_requested && s_rtc.rtm_logged_in && - generation == (uint32_t)aosl_atomic_read(&s_rtm_login_generation) && - s_rtc.callbacks.on_rtm_send_data_result) { - s_rtc.callbacks.on_rtm_send_data_result(rtm_uid, msg_id, (mybot_rtm_message_state_t)state, - s_rtc.callbacks.user_data); - } -} - static int login_rtm(const char *rtm_uid, const char *rtm_token) { if (!mybot_agora_rtc_rtm_uid_is_valid(rtm_uid)) { AOSL_LOG_ERR("[RTM] login rejected: invalid RTM UID"); @@ -705,20 +678,17 @@ static int login_rtm(const char *rtm_uid, const char *rtm_token) { memset(&handler, 0, sizeof(handler)); handler.on_rtm_event = on_rtm_event; handler.on_rtm_data = on_rtm_data; - handler.on_rtm_send_data_result = on_rtm_send_data_result; handler.on_rtm_subscribe_result = on_rtm_subscribe_result; handler.on_rtm_subscribe_data = on_rtm_subscribe_data; callback_gate_lock(); memcpy(s_rtc.rtm_uid, rtm_uid, strlen(rtm_uid) + 1); - s_rtc.rtm_owned_by_join = false; s_rtc.rtm_login_requested = true; if (++s_rtc.rtm_login_generation == 0) { s_rtc.rtm_login_generation = 1; } callback_gate_unlock(); aosl_atomic_set(&s_rtm_login_generation, s_rtc.rtm_login_generation); - s_rtc.rtm_login_completed = false; s_rtc.rtm_logged_in = false; aosl_atomic_set(&s_rtm_login_done, false); aosl_atomic_set(&s_rtm_login_ok, false); @@ -747,7 +717,6 @@ static int wait_for_rtm_login(const char *rtm_uid) { return -1; } if (completed) { - s_rtc.rtm_login_completed = true; s_rtc.rtm_logged_in = logged_in; if (!logged_in) { clear_rtm_login(); @@ -780,9 +749,7 @@ static void clear_rtm_login(void) { callback_gate_lock(); s_rtc.rtm_uid[0] = '\0'; s_rtc.rtm_login_requested = false; - s_rtc.rtm_login_completed = false; s_rtc.rtm_logged_in = false; - s_rtc.rtm_owned_by_join = false; callback_gate_unlock(); } @@ -1013,8 +980,7 @@ static void process_token_will_expire(connection_id_t conn_id, const char *token } } -/* RTSA invokes these handlers on its callback worker. They only copy the - * borrowed callback arguments and enqueue a non-blocking event for rtc_mpq. */ +/* Copy borrowed RTSA callback arguments, then enqueue them for rtc_mpq. */ static void on_rtm_event(const char *uid, rtm_event_type_e type, rtm_err_code_e error) { bool enabled; bool login_requested; @@ -1143,25 +1109,6 @@ static void on_rtm_subscribe_data(const char *channel, const char *uid, const vo } (void)rtc_event_queue(e); } -static void on_rtm_send_data_result(const char *uid, uint32_t id, rtm_msg_state_e state) { - bool enabled; - bool requested; - callback_gate_lock(); - enabled = aosl_atomic_read(&s_rtc_callbacks_enabled) != 0; - requested = s_rtc.rtm_login_requested; - callback_gate_unlock(); - if (!enabled || !uid || !requested || - strlen(uid) >= sizeof(((rtc_event_t *)0)->payload.rtm_send_result.uid_text)) - return; - rtc_event_t *e = rtc_event_new(RTC_EVENT_RTM_SEND_RESULT); - if (!e) - return; - memcpy(e->payload.rtm_send_result.uid_text, uid, strlen(uid) + 1U); - e->uid = id; - e->payload.rtm_send_result.state = state; - e->generation = (uint32_t)aosl_atomic_read(&s_rtm_login_generation); - (void)rtc_event_queue(e); -} static void on_join_channel_success(connection_id_t c, uint32_t uid, int elapsed) { queue_rtc_notification(RTC_EVENT_JOIN_SUCCESS, c, uid, elapsed); } @@ -1352,11 +1299,6 @@ static int rtc_init_impl(const char *app_id, const mybot_agora_rtc_callbacks_t * return 0; } -static int rtc_login_rtm_impl(const char *rtm_uid, const char *rtm_token) { - int ret = login_rtm(rtm_uid, rtm_token); - return ret; -} - static int rtc_logout_rtm_impl(void) { if (!s_rtc.rtm_login_requested) { clear_rtm_subscription(); @@ -1370,38 +1312,12 @@ static int rtc_logout_rtm_impl(void) { } else { AOSL_LOG_DBG("[RTM] logged out (uid=%s)", s_rtc.rtm_uid); } - /* Clear wrapper state even when the vendor call fails. Keeping a stale - * logged-in flag would block a later login and route sends to a dead - * session. */ + /* Clear wrapper state even when the vendor call fails so a later join can + * start a clean RTM session. */ clear_rtm_login(); return (unsubscribe_ret < 0 || ret < 0) ? -1 : 0; } -static bool rtc_is_rtm_logged_in_impl(void) { - bool logged_in = s_rtc.rtm_logged_in; - return logged_in; -} - -static int rtc_send_rtm_data_impl(const char *peer_rtm_uid, const void *data, size_t len, - uint32_t msg_id, const char *custom_type) { - if (!mybot_agora_rtc_rtm_uid_is_valid(peer_rtm_uid) || !data || len == 0 || len > 31U * 1024U || - (custom_type && strlen(custom_type) > 32U)) { - AOSL_LOG_ERR("[RTM] send rejected: invalid peer, payload, or custom type"); - return -1; - } - - if (!s_rtc.rtm_logged_in) { - AOSL_LOG_ERR("[RTM] send rejected: login has not completed"); - return -1; - } - int ret = - agora_rtm_send_data(peer_rtm_uid, data, len, msg_id, RTM_MESSAGE_TYPE_BINARY, custom_type); - if (ret < 0) { - AOSL_LOG_ERR("[RTM] send failed: %s", agora_rtc_err_2_str(ret)); - } - return ret; -} - static int rtc_join_impl(const char *channel, const char *token, const char *user_account, uint32_t video_min_bps, uint32_t video_max_bps) { if (!channel || !channel[0] || strlen(channel) >= AGORA_RTC_CHANNEL_NAME_MAX_LEN || @@ -1430,7 +1346,6 @@ static int rtc_join_impl(const char *channel, const char *token, const char *use return -1; } rtm_started_for_join = true; - s_rtc.rtm_owned_by_join = true; } if (wait_for_rtm_login(user_account) < 0) { @@ -1533,7 +1448,7 @@ static int rtc_leave_impl(void) { connection_id_t conn_id = s_rtc.conn_id; if (conn_id == CONNECTION_ID_INVALID) { - return s_rtc.rtm_owned_by_join ? rtc_logout_rtm_impl() : 0; + return rtc_logout_rtm_impl(); } s_rtc.conn_id = CONNECTION_ID_INVALID; @@ -1549,7 +1464,7 @@ static int rtc_leave_impl(void) { AOSL_LOG_NTC("[RTC] connection destroyed (conn_id=%u)", conn_id); } set_state(destroy_ret < 0 ? MYBOT_RTC_STATE_ERROR : MYBOT_RTC_STATE_INITIALIZED); - int rtm_ret = s_rtc.rtm_owned_by_join ? rtc_logout_rtm_impl() : unsubscribe_rtm(); + int rtm_ret = rtc_logout_rtm_impl(); return leave_ret < 0 || destroy_ret < 0 || rtm_ret < 0 ? -1 : 0; } @@ -1684,33 +1599,6 @@ static void cmd_init(const aosl_ts_t *ts, aosl_refobj_t ref, uintptr_t argc, uin rtc_init_impl((const char *)argv[1], (const mybot_agora_rtc_callbacks_t *)argv[2]); } } -static void cmd_login(const aosl_ts_t *ts, aosl_refobj_t ref, uintptr_t argc, uintptr_t argv[]) { - (void)ts; - (void)ref; - if (argc == 3) - *(int *)argv[0] = rtc_login_rtm_impl((const char *)argv[1], (const char *)argv[2]); -} -static void cmd_logout(const aosl_ts_t *ts, aosl_refobj_t ref, uintptr_t argc, uintptr_t argv[]) { - (void)ts; - (void)ref; - if (argc == 1) - *(int *)argv[0] = rtc_logout_rtm_impl(); -} -static void cmd_is_logged(const aosl_ts_t *ts, aosl_refobj_t ref, uintptr_t argc, - uintptr_t argv[]) { - (void)ts; - (void)ref; - if (argc == 1) - *(bool *)argv[0] = rtc_is_rtm_logged_in_impl(); -} -static void cmd_send_rtm(const aosl_ts_t *ts, aosl_refobj_t ref, uintptr_t argc, uintptr_t argv[]) { - (void)ts; - (void)ref; - if (argc == 6) - *(int *)argv[0] = - rtc_send_rtm_data_impl((const char *)argv[1], (const void *)argv[2], (size_t)argv[3], - (uint32_t)argv[4], (const char *)argv[5]); -} static void cmd_join(const aosl_ts_t *ts, aosl_refobj_t ref, uintptr_t argc, uintptr_t argv[]) { (void)ts; (void)ref; @@ -1783,29 +1671,6 @@ int mybot_agora_rtc_init(const char *app_id, const mybot_agora_rtc_callbacks_t * return result; } -int mybot_agora_rtc_login_rtm(const char *uid, const char *token) { - int result = -1; - uintptr_t argv[] = {(uintptr_t)&result, (uintptr_t)uid, (uintptr_t)token}; - return rtc_call("rtc_login", cmd_login, 3, argv) < 0 ? -1 : result; -} -int mybot_agora_rtc_logout_rtm(void) { - int result = -1; - uintptr_t argv[] = {(uintptr_t)&result}; - return rtc_call("rtc_logout", cmd_logout, 1, argv) < 0 ? -1 : result; -} -bool mybot_agora_rtc_is_rtm_logged_in(void) { - bool result = false; - uintptr_t argv[] = {(uintptr_t)&result}; - (void)rtc_call("rtc_is_logged", cmd_is_logged, 1, argv); - return result; -} -int mybot_agora_rtc_send_rtm_data(const char *peer, const void *data, size_t len, uint32_t id, - const char *custom) { - int result = -1; - uintptr_t argv[] = {(uintptr_t)&result, (uintptr_t)peer, (uintptr_t)data, - (uintptr_t)len, (uintptr_t)id, (uintptr_t)custom}; - return rtc_call("rtc_send_rtm", cmd_send_rtm, 6, argv) < 0 ? -1 : result; -} int mybot_agora_rtc_join(const char *channel, const char *token, const char *user, uint32_t video_min_bps, uint32_t video_max_bps) { int result = -1; diff --git a/components/mybot_stack/mybot_sdk/mybot/src/service/mybot_device_client.c b/components/mybot_stack/mybot_sdk/mybot/src/service/mybot_device_client.c index cca9e66..413efa5 100644 --- a/components/mybot_stack/mybot_sdk/mybot/src/service/mybot_device_client.c +++ b/components/mybot_stack/mybot_sdk/mybot/src/service/mybot_device_client.c @@ -11,18 +11,6 @@ #include #include -static bool header_value_is_safe(const char *value) { - if (!value || !value[0]) { - return false; - } - for (const unsigned char *p = (const unsigned char *)value; *p; p++) { - if (*p < 0x20 || *p == 0x7f) { - return false; - } - } - return true; -} - static bool url_unreserved(unsigned char c) { return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || (c >= '0' && c <= '9') || c == '-' || c == '.' || c == '_' || c == '~'; @@ -65,7 +53,7 @@ static int build_device_url(const char *base_url, const char *device_id, const c static int build_authorization_header(const char *scheme, const char *credential, char *header, size_t header_size) { - if (!scheme || !header_value_is_safe(credential)) { + if (!scheme || !mybot_http_header_value_is_safe(credential, false)) { return -1; } int written = snprintf(header, header_size, "Authorization: %s%s\r\n", scheme, credential); diff --git a/components/mybot_stack/mybot_sdk/mybot/src/support/mybot_http_client.c b/components/mybot_stack/mybot_sdk/mybot/src/support/mybot_http_client.c index 8623950..d8e8c78 100644 --- a/components/mybot_stack/mybot_sdk/mybot/src/support/mybot_http_client.c +++ b/components/mybot_stack/mybot_sdk/mybot/src/support/mybot_http_client.c @@ -1,6 +1,7 @@ /* SPDX-License-Identifier: Apache-2.0 */ #include "mybot_http_client.h" #include "mybot_https_transport.h" +#include "mybot_url.h" #include @@ -21,12 +22,9 @@ /* ---------------------------------------------------------- * Constants * ---------------------------------------------------------- */ -#define HTTP_DEFAULT_PORT 80 -#define HTTPS_DEFAULT_PORT 443 #define HTTP_TIMEOUT_MS 5000 /* shared deadline for connect/send/receive stages */ #define RECV_BUF_SIZE 4096 #define RECV_BUF_MAX (32 * 1024) /* hard cap on response buffer */ -#define MAX_URL_LEN 512 #define HTTP_REQUEST_BUFFER_SIZE 2048 static bool ascii_case_equal_n(const char *left, const char *right, size_t len) { @@ -56,53 +54,6 @@ static int deadline_remaining_ms(uint64_t deadline) { return remaining > INT_MAX ? INT_MAX : (int)remaining; } -/* ---------------------------------------------------------- - * Internal: URL parts - * ---------------------------------------------------------- */ -typedef struct { - bool use_tls; - char host[128]; - int port; - char path[512]; -} url_parts_t; - -static bool host_is_safe(const char *host) { - if (!host || !host[0]) { - return false; - } - for (const unsigned char *p = (const unsigned char *)host; *p; p++) { - if (*p <= 0x20 || *p > 0x7e || *p == '/' || *p == '\\' || *p == '?' || *p == '#' || - *p == '@') { - return false; - } - } - return true; -} - -static bool request_target_is_safe(const char *target) { - if (!target || target[0] != '/') { - return false; - } - for (const unsigned char *p = (const unsigned char *)target; *p; p++) { - if (*p <= 0x20 || *p > 0x7e || *p == '#' || *p == '\\') { - return false; - } - } - return true; -} - -static bool header_value_is_safe(const char *value) { - if (!value || !value[0]) { - return false; - } - for (const unsigned char *p = (const unsigned char *)value; *p; p++) { - if ((*p < 0x20 && *p != '\t') || *p > 0x7e) { - return false; - } - } - return true; -} - static bool header_name_char(unsigned char c) { return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || (c >= '0' && c <= '9') || c == '!' || c == '#' || c == '$' || c == '%' || c == '&' || c == '*' || c == '+' || c == '-' || @@ -141,89 +92,6 @@ static bool extra_headers_are_safe(const char *headers) { return true; } -/* - * Parse "https://host[:port][/path]" or an explicitly enabled HTTP URL. - * Returns 0 on success, -1 on error. - */ -static int parse_url(const char *url, url_parts_t *parts) { - if (!url || !parts) { - return -1; - } - - memset(parts, 0, sizeof(*parts)); - parts->path[0] = '/'; - - const char *p = url; - -#if MYBOT_ENABLE_HTTPS - if (strncmp(p, "https://", 8) == 0) { - parts->use_tls = true; - parts->port = HTTPS_DEFAULT_PORT; - p += 8; - } else -#endif -#if MYBOT_ALLOW_INSECURE_HTTP - if (strncmp(p, "http://", 7) == 0) { - parts->use_tls = false; - parts->port = HTTP_DEFAULT_PORT; - p += 7; - } else -#endif - { - return -1; - } - - /* Extract host (up to ':', '/', or the end). */ - const char *host_start = p; - while (*p && *p != ':' && *p != '/') { - p++; - } - size_t host_len = (size_t)(p - host_start); - if (host_len == 0 || host_len >= sizeof(parts->host)) { - return -1; - } - memcpy(parts->host, host_start, host_len); - parts->host[host_len] = '\0'; - if (!host_is_safe(parts->host)) { - return -1; - } - - /* Parse an optional port. */ - if (*p == ':') { - p++; - char port_str[8]; - int pi = 0; - while (*p >= '0' && *p <= '9' && pi < (int)sizeof(port_str) - 1) { - port_str[pi++] = *p++; - } - port_str[pi] = '\0'; - if (pi == 0) { - return -1; - } - parts->port = atoi(port_str); - if (parts->port <= 0 || parts->port > 65535) { - return -1; - } - } - - /* Parse the path, defaulting to "/". */ - if (*p == '/') { - size_t path_len = strlen(p); - if (path_len >= sizeof(parts->path)) { - return -1; - } - memcpy(parts->path, p, path_len + 1); - } else if (*p != '\0') { - return -1; - } - - if (!request_target_is_safe(parts->path)) { - return -1; - } - - return 0; -} - static aosl_fd_t tcp_connect(const char *host, int port, uint64_t deadline); static int parse_content_length(const char *value, const char *end, size_t *out_length); @@ -273,7 +141,8 @@ typedef struct { void *tls_connection; } http_stream_t; -static int stream_connect(http_stream_t *stream, const url_parts_t *parts, uint64_t deadline) { +static int stream_connect(http_stream_t *stream, const mybot_url_parts_t *parts, + uint64_t deadline) { memset(stream, 0, sizeof(*stream)); stream->fd = AOSL_INVALID_FD; stream->use_tls = parts->use_tls; @@ -797,11 +666,11 @@ static int http_request(const char *method, const char *url, const char *content mybot_http_client_response_t *resp) { uint64_t deadline = aosl_hal_get_tick_ms() + HTTP_TIMEOUT_MS; - url_parts_t parts; - if (parse_url(url, &parts) < 0) { + mybot_url_parts_t parts; + if (mybot_url_parse(url, &parts) < 0) { return -1; } - if ((content_type && !header_value_is_safe(content_type)) || + if ((content_type && !mybot_http_header_value_is_safe(content_type, true)) || !extra_headers_are_safe(extra_headers)) { return -1; } @@ -819,8 +688,8 @@ static int http_request(const char *method, const char *url, const char *content return -1; } char host_header[sizeof(parts.host) + 8]; - bool include_port = (parts.use_tls && parts.port != HTTPS_DEFAULT_PORT) || - (!parts.use_tls && parts.port != HTTP_DEFAULT_PORT); + bool include_port = (parts.use_tls && parts.port != MYBOT_URL_HTTPS_PORT) || + (!parts.use_tls && parts.port != MYBOT_URL_HTTP_PORT); int host_len = include_port ? snprintf(host_header, sizeof(host_header), "%s:%d", parts.host, parts.port) : snprintf(host_header, sizeof(host_header), "%s", parts.host); diff --git a/components/mybot_stack/mybot_sdk/mybot/src/support/mybot_http_header.c b/components/mybot_stack/mybot_sdk/mybot/src/support/mybot_http_header.c new file mode 100644 index 0000000..0892c03 --- /dev/null +++ b/components/mybot_stack/mybot_sdk/mybot/src/support/mybot_http_header.c @@ -0,0 +1,16 @@ +/* SPDX-License-Identifier: Apache-2.0 */ +#include "mybot_http_client.h" + +#include + +bool mybot_http_header_value_is_safe(const char *value, bool allow_tab) { + if (!value || !value[0]) { + return false; + } + for (const unsigned char *p = (const unsigned char *)value; *p; p++) { + if ((*p < 0x20 && !(allow_tab && *p == '\t')) || *p > 0x7e) { + return false; + } + } + return true; +} diff --git a/components/mybot_stack/mybot_sdk/mybot/src/support/mybot_ringbuf.c b/components/mybot_stack/mybot_sdk/mybot/src/support/mybot_ringbuf.c index 25c2ebc..6a5b75c 100644 --- a/components/mybot_stack/mybot_sdk/mybot/src/support/mybot_ringbuf.c +++ b/components/mybot_stack/mybot_sdk/mybot/src/support/mybot_ringbuf.c @@ -61,16 +61,6 @@ int mybot_ringbuf_destroy(mybot_ringbuf_t handle) { return 0; } -int mybot_ringbuf_clear(mybot_ringbuf_t handle) { - if (!handle) { - return -1; - } - ringbuf_internal_t *rb = (ringbuf_internal_t *)handle; - aosl_atomic_set(&rb->head, 0); - aosl_atomic_set(&rb->tail, 0); - return 0; -} - int mybot_ringbuf_get_free_size(mybot_ringbuf_t handle) { if (!handle) { return -1; diff --git a/components/mybot_stack/mybot_sdk/mybot/src/support/mybot_url.c b/components/mybot_stack/mybot_sdk/mybot/src/support/mybot_url.c new file mode 100644 index 0000000..f387f60 --- /dev/null +++ b/components/mybot_stack/mybot_sdk/mybot/src/support/mybot_url.c @@ -0,0 +1,106 @@ +/* SPDX-License-Identifier: Apache-2.0 */ +#include "mybot_url.h" + +#include + +#include + +static bool host_is_safe(const char *host) { + if (!host || !host[0]) { + return false; + } + for (const unsigned char *p = (const unsigned char *)host; *p; p++) { + if (*p <= 0x20 || *p > 0x7e || *p == '/' || *p == '\\' || *p == '?' || *p == '#' || + *p == '@') { + return false; + } + } + return true; +} + +static bool request_target_is_safe(const char *target) { + if (!target || target[0] != '/') { + return false; + } + for (const unsigned char *p = (const unsigned char *)target; *p; p++) { + if (*p <= 0x20 || *p > 0x7e || *p == '#' || *p == '\\') { + return false; + } + } + return true; +} + +int mybot_url_parse(const char *url, mybot_url_parts_t *parts) { + if (!url || !parts) { + return -1; + } + + memset(parts, 0, sizeof(*parts)); + parts->path[0] = '/'; + + const char *p = url; + +#if MYBOT_ENABLE_HTTPS + if (strncmp(p, "https://", 8) == 0) { + parts->use_tls = true; + parts->port = MYBOT_URL_HTTPS_PORT; + p += 8; + } else +#endif +#if MYBOT_ALLOW_INSECURE_HTTP + if (strncmp(p, "http://", 7) == 0) { + parts->use_tls = false; + parts->port = MYBOT_URL_HTTP_PORT; + p += 7; + } else +#endif + { + return -1; + } + + const char *host_start = p; + while (*p && *p != ':' && *p != '/') { + p++; + } + size_t host_len = (size_t)(p - host_start); + if (host_len == 0 || host_len >= sizeof(parts->host)) { + return -1; + } + memcpy(parts->host, host_start, host_len); + parts->host[host_len] = '\0'; + if (!host_is_safe(parts->host)) { + return -1; + } + + if (*p == ':') { + p++; + if (*p < '0' || *p > '9') { + return -1; + } + unsigned int port = 0; + while (*p >= '0' && *p <= '9') { + unsigned int digit = (unsigned int)(*p - '0'); + if (port > 6553U || (port == 6553U && digit > 5U)) { + return -1; + } + port = port * 10U + digit; + p++; + } + if (port == 0) { + return -1; + } + parts->port = (int)port; + } + + if (*p == '/') { + size_t path_len = strlen(p); + if (path_len >= sizeof(parts->path)) { + return -1; + } + memcpy(parts->path, p, path_len + 1U); + } else if (*p != '\0') { + return -1; + } + + return request_target_is_safe(parts->path) ? 0 : -1; +} diff --git a/docs/AUDIO_PLAYBACK.md b/docs/AUDIO_PLAYBACK.md index 88b0584..28dac40 100644 --- a/docs/AUDIO_PLAYBACK.md +++ b/docs/AUDIO_PLAYBACK.md @@ -84,11 +84,9 @@ SDK packet delivery. The removed renderer's `event=ui_stats` is no longer emitte `rebuffer_events` estimates when playback needs buffering again and may include speech pauses. It is not a DMA-underrun counter. -CoreS3 real-device testing passed all three offline stages after buffering was added; normal -conversations also passed with video enabled and disabled. That is the recorded hardware baseline. -The subsequent shared-buffer extraction and platform/UI changes still need per-board regression; -host simulations and firmware builds cannot establish their audible result. The -[offline comparison](CORES3_AUDIO_TEST.md) remains CoreS3-only. +Current build and hardware status is tracked only in the +[validation matrix](VALIDATION.md). Host simulations and firmware builds cannot establish the +audible result. The [offline comparison](CORES3_AUDIO_TEST.md) remains CoreS3-only. For each additional board, test continuous conversation with capture active, first-boot and button-triggered Wi-Fi prompts, pairing-code tails, repeated hangup/restart, volume persistence, diff --git a/docs/AUDIO_PLAYBACK.zh-CN.md b/docs/AUDIO_PLAYBACK.zh-CN.md index 7b2ad22..d9ab567 100644 --- a/docs/AUDIO_PLAYBACK.zh-CN.md +++ b/docs/AUDIO_PLAYBACK.zh-CN.md @@ -77,9 +77,8 @@ I2S 接受数据后额外等待 120 ms,覆盖当前 90 ms 的 DMA 容量。这 `rebuffer_events` 估算重新缓冲的次数, 可能包含正常语音停顿,不是 DMA 断供计数。 -CoreS3 增加缓冲后,三个离线阶段均已通过真机听音测试,普通对话在视频开启、关闭两种 -情况下也已验证正常。这是已记录的硬件验证基线;后续公共缓冲抽取及平台/UI 变化仍需 -逐板回归,主机模拟及固件编译不能证明实际听音结果。 +当前构建与真机状态统一记录在[验证矩阵](VALIDATION.md)中。主机模拟及固件编译不能证明 +实际听音结果。 [离线对照测试](CORES3_AUDIO_TEST.zh-CN.md)仍仅支持 CoreS3。 其他板型应逐一验证:持续采集时的连续对话、首次启动及按键触发的配网提示音、配对码尾音、 diff --git a/docs/CORES3_AUDIO_TEST.md b/docs/CORES3_AUDIO_TEST.md index 48a3b47..9d48502 100644 --- a/docs/CORES3_AUDIO_TEST.md +++ b/docs/CORES3_AUDIO_TEST.md @@ -24,9 +24,9 @@ agent-studio-device-firmware SDK, 16 kHz sample rate, and codec settings remain Buffering adds playback latency: after the offline test, verify normal conversations, end-of-speech tails, interruption/hangup, and Cloud AEC. -The three buffered stages have already passed CoreS3 real-device listening tests, as have normal -conversations with video enabled and disabled. The later shared-buffer extraction and platform/UI -changes still need regression testing; those changes do not establish results for other boards. +Current build and hardware status is tracked only in the +[validation matrix](VALIDATION.md). Results from this test do not establish behavior for other +boards. ## Build and run diff --git a/docs/CORES3_AUDIO_TEST.zh-CN.md b/docs/CORES3_AUDIO_TEST.zh-CN.md index 9484031..e0b209e 100644 --- a/docs/CORES3_AUDIO_TEST.zh-CN.md +++ b/docs/CORES3_AUDIO_TEST.zh-CN.md @@ -21,8 +21,8 @@ CoreS3 将 PCM 接收到有界 FIFO,容量为 3,840 个采样点(7,680 字 agent-studio-device-firmware SDK、16 kHz 采样率及 codec 配置保持不变。 预缓冲会增加播放延迟:离线测试后还需验证普通对话、尾音、打断/挂断及 Cloud AEC。 -增加缓冲后的三个阶段已通过 CoreS3 真机听音测试,普通对话在视频开启、关闭两种情况下 -也已验证正常。后续公共缓冲抽取及平台/UI 变化仍需回归,也不能替代其他板型的真机验证。 +当前构建与真机状态统一记录在[验证矩阵](VALIDATION.md)中。本测试结果不能替代其他板型的 +真机验证。 ## 构建与运行 diff --git a/docs/CORES3_VIDEO.md b/docs/CORES3_VIDEO.md index 165fa96..e50bbf5 100644 --- a/docs/CORES3_VIDEO.md +++ b/docs/CORES3_VIDEO.md @@ -83,6 +83,10 @@ result in fewer than one delivered frame per second. SDK acceptance does not pro ## Diagnostics and acceptance +Current build and hardware status is tracked only in the +[validation matrix](VALIDATION.md). The following checks remain the device and server acceptance +procedure. + `cores3_video` emits lifecycle logs and `event=video_stats` every 10 seconds during streaming: `window_ms`, `captured`, `encoded`, `sent`, `rejected`, `dropped`, `capture_errors`, `last_bytes`, `quality`, `target_bps`, and `encode_max_us`. Counters and `encode_max_us` reset each interval; `last_bytes`, `quality`, and @@ -92,14 +96,10 @@ requested while the queue is empty do not count as `dropped`. `sent` means RTSA callback. Normal capture can approach 50 frames per 10 seconds; encoding/send duration and 200 ms sampling intervals can put uplink near 8–10 frames per 10 seconds, always capped at 1 fps. -CoreS3 camera bring-up has already passed real-device testing. Normal audio was also verified with -video enabled and disabled. These are the recorded hardware results; the newer capture scheduling, -larger DMA buffer, and UI changes still require hardware regression and CPU measurements. - Validate GC0308 detection, correct colors/orientation, server reception/inference, send spacing, JPEG quality, CPU/heap use, and audio continuity. Exercise repeated conversation start/stop, Wi-Fi loss, long-touch provisioning, bitrate reduction, and missing camera. Confirm no frames after -stop and stable memory after repeated cycles. Both Chinese/English video builds are covered in CI; -hardware and server acceptance must be recorded separately. Compare `captured/window_ms`, +stop and stable memory after repeated cycles. Hardware and server acceptance must be recorded +separately. Compare `captured/window_ms`, per-core CPU, internal free heap, and the largest free block while keeping the same scene and audio activity. The expected reduction in DMA traffic is not a measured CPU reduction. diff --git a/docs/CORES3_VIDEO.zh-CN.md b/docs/CORES3_VIDEO.zh-CN.md index 26128a2..7e7a68d 100644 --- a/docs/CORES3_VIDEO.zh-CN.md +++ b/docs/CORES3_VIDEO.zh-CN.md @@ -71,6 +71,8 @@ Board 常驻 I2C 总线。 ## 日志与验收 +当前构建与真机状态统一记录在[验证矩阵](VALIDATION.md)中。以下项目是真机与服务端验收流程。 + `cores3_video` 打印生命周期日志,推流时每 10 秒汇总 `event=video_stats`:窗口时长 `window_ms`、成功出队数 `captured`、编码数 `encoded`、接受数 `sent`、拒绝数 `rejected`、 丢帧数 `dropped`、采集错误 `capture_errors`、 @@ -81,11 +83,8 @@ Board 常驻 I2C 总线。 `sent` 表示 SDK/RTSA 接受发送。正常采集可接近每 10 秒 50 帧;受编码、发送耗时及 200 ms 采样间隔影响,上行可能约每 10 秒 8–10 帧,始终不超过 1 fps。 -CoreS3 摄像头已完成真机调通;普通音频在视频开启和关闭两种场景下也已验证正常。 -这是已有的硬件验证记录,本次采集调度、增大的 DMA 缓冲及 UI 变化仍需真机回归和 CPU 测量。 - 真机需验证 GC0308 识别、颜色与方向、服务端收到并识别图像、发送间隔、图像质量、CPU/内存 以及音频连续性。覆盖重复开始/结束对话、断网、长按触摸配网、带宽降低和摄像头缺失,确认 -停止后无回调、多轮运行无内存持续增长。CI 覆盖中英文视频构建;真机和服务端验收另行记录。 +停止后无回调、多轮运行无内存持续增长。真机和服务端验收另行记录。 对比测试应保持相同场景和音频活动,观察 `captured/window_ms`、每核 CPU、内部剩余堆和 最大连续块;DMA 流量的理论减少不等于已经测得 CPU 降幅。 diff --git a/docs/RELEASING.md b/docs/RELEASING.md index fd7416f..87c4314 100644 --- a/docs/RELEASING.md +++ b/docs/RELEASING.md @@ -5,7 +5,8 @@ ## Prepare - [ ] Choose a Semantic Version and update `PROJECT_VER` in `CMakeLists.txt` and `CHANGELOG.md`. -- [ ] Confirm README, board support, known limitations, and configuration documentation are current. +- [ ] Confirm README, board support and configuration documentation are current, and update the + single [validation matrix](VALIDATION.md) for this release. - [ ] Review all dependency revisions, bundled licenses, and `THIRD_PARTY_NOTICES.md`. - [ ] Verify the agent-studio-device-firmware snapshot, AOSL sources, and RTSA headers/library in `components/mybot_stack` match `VENDORED_SOURCES.md`; keep the SDK snapshot unchanged @@ -27,9 +28,8 @@ idf.py -B build/release size git diff --check ``` -- [ ] All 30 firmware builds in the [CI workflow](../.github/workflows/ci.yml) pass: thirteen boards - in both languages, two additional CoreS3 video builds, one CoreS3 light-theme build, and one - CoreS3 video build with conversation animations disabled. All use 60 ms audio frames. +- [ ] All firmware builds in the [CI workflow](../.github/workflows/ci.yml) pass. All use 60 ms + audio frames. - [ ] Confirm unsupported 20 ms and 40 ms settings still fail configuration with the bundled RTSA. - [ ] Record firmware builds, host-side tests, and real-device results separately. Host layout or lifecycle tests do not validate panel transfers, power sequencing, or acoustic performance. @@ -103,4 +103,5 @@ git diff --check - [ ] Create an annotated `v` tag matching `PROJECT_VER`. - [ ] Attach source and firmware artifacts only after third-party authorization review. - [ ] Include `LICENSE`, `THIRD_PARTY_NOTICES.md`, the changelog, partition layout, and checksums. -- [ ] List known limitations and distinguish build validation from real-hardware validation. +- [ ] Confirm the [validation matrix](VALIDATION.md) distinguishes build coverage from real-hardware + results and lists current limitations. diff --git a/docs/RELEASING.zh-CN.md b/docs/RELEASING.zh-CN.md index e8b4d10..1c156f5 100644 --- a/docs/RELEASING.zh-CN.md +++ b/docs/RELEASING.zh-CN.md @@ -5,7 +5,8 @@ ## 准备 - [ ] 确定语义化版本,并同步更新 `CMakeLists.txt` 中的 `PROJECT_VER` 与 `CHANGELOG.md`。 -- [ ] 确认 README、板卡支持、已知限制与配置文档符合当前实现。 +- [ ] 确认 README、板卡支持与配置文档符合当前实现,并更新唯一的 + [验证矩阵](VALIDATION.md)。 - [ ] 审查全部依赖版本、随附许可证与 `THIRD_PARTY_NOTICES.md`。 - [ ] 核对 `components/mybot_stack` 中的 agent-studio-device-firmware 快照、AOSL 源码及 RTSA 头文件/库与 `VENDORED_SOURCES.md` 一致;除明确同步上游版本外,不修改 SDK 快照。 @@ -25,9 +26,8 @@ idf.py -B build/release size git diff --check ``` -- [ ] [CI 工作流](../.github/workflows/ci.yml)的 30 项固件构建全部通过:十三个板型分别构建 - 中英文版本,另加 CoreS3 两种语言的视频构建、一个浅色主题构建,以及一个关闭会话 - 动画的视频构建。所有构建使用 60 ms 音频帧。 +- [ ] [CI 工作流](../.github/workflows/ci.yml)中的固件构建全部通过,所有构建使用 60 ms + 音频帧。 - [ ] 确认随附 RTSA 仍会在配置阶段拒绝不支持的 20 ms 和 40 ms 设置。 - [ ] 分别记录固件构建、主机测试和真机结果。主机布局或生命周期测试不能验证屏幕传输、 上电时序或声学表现。 @@ -91,4 +91,4 @@ git diff --check - [ ] 创建与 `PROJECT_VER` 一致的带注释 `v` tag。 - [ ] 仅在第三方授权审查后附加源码与固件制品。 - [ ] 包含 `LICENSE`、`THIRD_PARTY_NOTICES.md`、changelog、分区布局与校验和。 -- [ ] 列出已知限制,并区分编译验证与真实硬件验证。 +- [ ] 确认[验证矩阵](VALIDATION.md)区分构建覆盖与真机结果,并列出当前限制。 diff --git a/docs/VALIDATION.md b/docs/VALIDATION.md new file mode 100644 index 0000000..a024e42 --- /dev/null +++ b/docs/VALIDATION.md @@ -0,0 +1,46 @@ +# Validation matrix / 验证矩阵 + +This is the single source of truth for current build coverage, real-device results and known +unsupported areas. Board READMEs describe hardware and operation only; the +[release checklist](RELEASING.md) describes required checks, not completed results. + +本文档是构建覆盖、真机结果和已知未支持能力的唯一状态来源。板卡 README 只描述硬件与操作, +[发布检查清单](RELEASING.zh-CN.md)描述发布前必须执行的检查,不表示这些检查已经完成。 + +## Legend / 图例 + +- **CI build / CI 构建**: Both `zh-CN` and `en-US` are present in the + [CI matrix](../.github/workflows/ci.yml). This is coverage unless recorded build evidence is + explicitly listed. +- **Recorded build / 已记录构建**: The repository contains a specific successful + `reconfigure/build/size/merge-bin` result for that profile. +- **Hardware / 真机**: Results recorded from physical devices. A successful build or host test + does not satisfy this column. + +## Matrix / 矩阵 + +| Board profile | Build evidence / 构建证据 | Hardware / 真机 | Unsupported or unverified / 未支持或待验证 | +| --- | --- | --- | --- | +| `atom-echos3r` | CI: zh-CN, en-US | Not completed / 未完成 | GPIO41 mapping and polarity, 16 kHz bidirectional audio; no display or video. | +| `bread-compact-wifi-lcd` | CI: zh-CN, en-US; recorded merged build / 已记录合并构建 | Not completed / 未完成 | Capacity, panel, backlight, audio and repeated provisioning; no touch, camera, volume keys, LED, lamp or power management. | +| `esp-vocat` | CI: zh-CN, en-US | Not completed / 未完成 | Both PCB revisions still require power, pin-map, audio and touch validation; no battery, IMU, slider, SD, LED, camera expansion, local AEC, reference audio, shutdown or low power. | +| `esp32-s3-touch-amoled-1.75` | CI: zh-CN, en-US | Not completed / 未完成 | Power, audio slots, display and touch; no video, playback reference, local AEC, RTC, IMU, TF card, battery reporting, sleep or shutdown. | +| `esp32-s3-touch-amoled-1.75c` | CI: zh-CN, en-US | Not completed / 未完成 | Same as 1.75, with no TCA9554 support; verify detected Flash capacity before expanding the partition layout. | +| `esp32-s3-touch-amoled-2.16` | CI: zh-CN, en-US; recorded merged build / 已记录合并构建 | Not completed / 未完成 | Physical Flash/PSRAM and TCA9554 presence, power, 480x480 display, touch and audio; no video, playback reference, local AEC, RTC, IMU, TF card, battery reporting, sleep or shutdown. | +| `m5stack-core-s3` | CI: zh-CN, en-US, video, light-theme and static-animation variants; recorded video build / 已记录视频构建 | Partial / 部分通过: earlier provisioning, bidirectional audio, camera uplink and status-card UI; current pixel UI and shared UI changes pending / 旧通路通过,当前像素 UI 与共享 UI 待回归 | Current pixel UI, capture scheduling and DMA regression; no video downlink, camera preview, battery reporting or automatic sleep. Video is opt-in for direct builds. | +| `m5stack-stick-s3` | CI: zh-CN, en-US | Not completed / 未完成 | Power, audio, input and panel; no GPIO12 support, IMU, infrared, battery reporting, shutdown or low power. | +| `respeaker-flex-xvf3800-circular4-xiao` | CI: zh-CN, en-US | Not completed / 未完成 | Requires separately flashed XVF3800 Circular-4 16 kHz two-channel I2S firmware; XVF version, clock direction, routing and audio pending. No Linear-4, XVF firmware update, LED ring, LCD or video. | +| `sensecap-watcher` | CI: zh-CN, en-US | Not completed / 未完成 | Power sequencing, codec 16 kHz mode, audio, encoder and display; no camera, touch, LED, battery reporting, shutdown or low power. Preserve the factory-data partition. | +| `xingzhi-cube-1.54tft-wifi` | CI: zh-CN, en-US; recorded merged build / 已记录合并构建 | Not completed / 未完成 | Physical Flash/PSRAM, GPIO21 power hold, backlight, display, buttons and 16 kHz audio; no touch, video, battery/charging, shutdown, sleep or low power. | +| `zhengchen-1.54tft-ml307` | CI: zh-CN, en-US | Not completed / 未完成 | ML307/4G is not implemented; Wi-Fi remains the network path. Audio, panel and buttons still need device validation; no battery status, temperature monitoring, sleep or low power. | +| `zhengchen-1.54tft-wifi` | CI: zh-CN, en-US | Not completed / 未完成 | Physical PSRAM capacity, audio, panel and buttons still need device validation; no modem/4G, battery/charging, temperature monitoring, sleep or low power. | + +## Global boundaries / 全局边界 + +- Local wake words are not implemented. +- ML307/4G networking is not implemented; all profiles use Wi-Fi. +- Only `m5stack-core-s3` currently implements encoded video uplink. +- NVS encryption, Flash encryption and Secure Boot belong to product provisioning rather than + these default firmware profiles. + +状态变化时只更新本矩阵;专题文档和板卡 README 应链接到这里,不再复制验证状态。 diff --git a/tests/cores3_pixel_ui/README.md b/tests/cores3_pixel_ui/README.md index 3463cbd..caf62c9 100644 --- a/tests/cores3_pixel_ui/README.md +++ b/tests/cores3_pixel_ui/README.md @@ -6,6 +6,5 @@ CoreS3 panel, LVGL port, Wi-Fi SSID snapshot, and view. It does not use hardware Coverage includes partial initialization failures, retryable cleanup, board/SDK display references, pending DMA callbacks, copied pair codes and SSIDs, runtime -status, same-emotion replay, phase transitions, foreground expiry, hangup and -detach cancellation, malformed emotions, and a new command arriving between -view submission and foreground-clock acknowledgement. +status, automatic phase transitions, opener timing and retry, unknown indicator +mask handling, hangup and detach cancellation. diff --git a/tests/cores3_pixel_ui/test_adapter.cc b/tests/cores3_pixel_ui/test_adapter.cc index 097f63a..292d127 100644 --- a/tests/cores3_pixel_ui/test_adapter.cc +++ b/tests/cores3_pixel_ui/test_adapter.cc @@ -41,14 +41,14 @@ static host_panel panel{}; static host_display display{}; static host_timer timer{}; static bool port_open, port_locked, view_open, finish_on_delay; -static unsigned pending_dma, replay_count, updates, closes; +static unsigned pending_dma, updates, closes; static int64_t now_us; static std::string fail_step, fail_cleanup; static mybot_lcd_content_t applied{}; static mybot_display_runtime_status_t applied_runtime{}; static std::string applied_ssid; static mybot_expression_t visible = MYBOT_EXPRESSION_NEUTRAL; -static bool replay_ok = true, inject_same_command, inject_phase_update; +static bool replay_ok = true; static void *active_owner; extern "C" const mybot_lcd_ops_t *mybot_cores3_lcd_ops(void); @@ -255,19 +255,10 @@ int mybot_pixel_glasses_show_expression(mybot_expression_t expression) { } int mybot_pixel_glasses_replay_expression(mybot_expression_t expression) { CHECK(view_open && port_locked); + if (!replay_ok) + return -1; visible = expression; - ++replay_count; - if (inject_same_command) { - inject_same_command = false; - send(MYBOT_LCD_SCREEN_IN_CONVERSATION, MYBOT_LCD_INDICATOR_HAPPY); - } - if (inject_phase_update) { - inject_phase_update = false; - send(MYBOT_LCD_SCREEN_IN_CONVERSATION, - MYBOT_LCD_INDICATOR_THINKING | MYBOT_LCD_INDICATOR_VP_REGISTERED); - CHECK(mybot_display_set_runtime_status("in_conversation", true) == 0); - } - return replay_ok ? 0 : -1; + return 0; } } @@ -349,64 +340,37 @@ static void ui_tests() { CHECK(visible == MYBOT_EXPRESSION_SURPRISED); tick(1); CHECK(visible == MYBOT_EXPRESSION_LISTENING); - send(MYBOT_LCD_SCREEN_IN_CONVERSATION, MYBOT_LCD_INDICATOR_HAPPY); - tick(); - CHECK(visible == MYBOT_EXPRESSION_HAPPY && - !(applied.indicators & MYBOT_LCD_INDICATOR_EMOTION_MASK)); - const unsigned played = replay_count; - send(MYBOT_LCD_SCREEN_IN_CONVERSATION, MYBOT_LCD_INDICATOR_HAPPY); - tick(); - CHECK(replay_count == played + 1); send(MYBOT_LCD_SCREEN_IN_CONVERSATION, MYBOT_LCD_INDICATOR_THINKING); - tick(500); - CHECK(visible == MYBOT_EXPRESSION_HAPPY && replay_count == played + 1); - CHECK(mybot_display_set_runtime_status("in_conversation", true) == 0); - tick(1749); - CHECK(visible == MYBOT_EXPRESSION_HAPPY); - tick(1); + tick(); CHECK(visible == MYBOT_EXPRESSION_THINKING); - tick(750); + tick(2999); + CHECK(visible == MYBOT_EXPRESSION_THINKING); + tick(1); CHECK(visible == MYBOT_EXPRESSION_PROCESSING); - send(MYBOT_LCD_SCREEN_IN_CONVERSATION, MYBOT_LCD_INDICATOR_SAD); + send(MYBOT_LCD_SCREEN_IN_CONVERSATION, + MYBOT_LCD_INDICATOR_LISTENING | MYBOT_LCD_INDICATOR_VP_REGISTERED); tick(); + CHECK(visible == MYBOT_EXPRESSION_LISTENING); + CHECK(applied.indicators == + (MYBOT_LCD_INDICATOR_LISTENING | MYBOT_LCD_INDICATOR_VP_REGISTERED)); + send(MYBOT_LCD_SCREEN_READY); tick(); CHECK(visible == MYBOT_EXPRESSION_NEUTRAL); - - send(MYBOT_LCD_SCREEN_IN_CONVERSATION, MYBOT_LCD_INDICATOR_HAPPY); - inject_same_command = true; - const unsigned race_before = replay_count; + replay_ok = false; + send(MYBOT_LCD_SCREEN_IN_CONVERSATION, MYBOT_LCD_INDICATOR_LISTENING); tick(); - tick(10); - CHECK(replay_count == race_before + 2); - tick(2249); - CHECK(visible == MYBOT_EXPRESSION_HAPPY); - tick(1); CHECK(visible == MYBOT_EXPRESSION_NEUTRAL); - send(MYBOT_LCD_SCREEN_IN_CONVERSATION, MYBOT_LCD_INDICATOR_HAPPY); - inject_phase_update = true; - const unsigned overlay_before = replay_count; - tick(); + replay_ok = true; tick(); - CHECK(replay_count == overlay_before + 1); - tick(2250); - CHECK(visible == MYBOT_EXPRESSION_THINKING); - tick(750); - CHECK(visible == MYBOT_EXPRESSION_PROCESSING); + CHECK(visible == MYBOT_EXPRESSION_SURPRISED); - replay_ok = false; - send(MYBOT_LCD_SCREEN_IN_CONVERSATION, - MYBOT_LCD_INDICATOR_HAPPY | MYBOT_LCD_INDICATOR_THINKING); - tick(); - tick(3000); - CHECK(visible == MYBOT_EXPRESSION_HAPPY); // failed submissions don't start hold - replay_ok = true; + send(MYBOT_LCD_SCREEN_IN_CONVERSATION, MYBOT_LCD_INDICATOR_LISTENING | (1u << 31)); tick(); - tick(2250); - CHECK(visible == MYBOT_EXPRESSION_PROCESSING); + CHECK(visible == MYBOT_EXPRESSION_SURPRISED); + void *sdk = nullptr; CHECK(mybot_cores3_lcd_ops()->init(&sdk) == 0 && sdk == active_owner); - send(MYBOT_LCD_SCREEN_IN_CONVERSATION, MYBOT_LCD_INDICATOR_HAPPY); tick(); mybot_cores3_lcd_ops()->destroy(sdk); tick(); @@ -414,10 +378,6 @@ static void ui_tests() { send(MYBOT_LCD_SCREEN_WIFI_PROVISIONING); tick(); CHECK(applied_ssid == "mybot-test"); - mybot_lcd_content_t bad{}; - bad.screen = MYBOT_LCD_SCREEN_IN_CONVERSATION; - bad.indicators = MYBOT_LCD_INDICATOR_HAPPY | MYBOT_LCD_INDICATOR_SAD; - CHECK(mybot_cores3_lcd_ops()->render(active_owner, &bad) < 0); stop(); CHECK(mybot_display_set_runtime_status("ready", false) < 0); } @@ -425,5 +385,5 @@ static void ui_tests() { int main() { lifecycle_tests(); ui_tests(); - std::puts("CoreS3 pixel adapter: lifecycle, DMA, policy and command-race checks passed"); + std::puts("CoreS3 pixel adapter: lifecycle, DMA, indicator and phase checks passed"); }