From 7e8c30b99e0977e8ddc05ca036bb1e961a709b3f Mon Sep 17 00:00:00 2001 From: shangjinlong Date: Fri, 23 Oct 2026 15:33:57 +0800 Subject: [PATCH 1/2] chore(sdk): sync mybot to baf41ba --- CHANGELOG.md | 10 +- THIRD_PARTY_NOTICES.md | 2 +- VENDORED_SOURCES.md | 2 +- .../src/drivers/display/README.md | 8 +- .../adapters/lvgl/ili9342_lvgl_adapter.cc | 31 +--- .../renderers/lvgl/PIXEL_GLASSES_SOURCES.md | 8 +- .../src/internal/display/expression_policy.h | 52 +------ .../mybot_stack/mybot_sdk/CMakeLists.txt | 2 + .../mybot_stack/mybot_sdk/mybot/CHANGELOG.md | 16 ++ .../mybot_sdk/mybot/THIRD_PARTY_NOTICES.md | 7 +- .../mybot/include/mybot/platform/mybot_lcd.h | 28 +--- .../mybot_sdk/mybot/src/core/mybot_app.c | 55 +------ .../mybot/src/core/mybot_presenter.c | 19 --- .../mybot/src/internal/mybot_agora_rtc.h | 37 +---- .../src/internal/mybot_announce_internal.h | 20 +-- .../mybot/src/internal/mybot_audio_internal.h | 34 +--- .../src/internal/mybot_device_lifecycle.h | 29 +--- .../mybot/src/internal/mybot_http_client.h | 5 + .../mybot/src/internal/mybot_key_internal.h | 6 - .../src/internal/mybot_kv_store_internal.h | 7 - .../mybot/src/internal/mybot_lcd_internal.h | 10 +- .../mybot/src/internal/mybot_media_pipeline.h | 5 +- .../mybot/src/internal/mybot_presenter.h | 2 - .../mybot/src/internal/mybot_ringbuf.h | 9 +- .../mybot_sdk/mybot/src/internal/mybot_url.h | 40 +++++ .../src/internal/mybot_wake_words_internal.h | 7 - .../mybot/src/internal/mybot_wifi_internal.h | 7 - .../mybot/src/media/mybot_media_pipeline.c | 16 +- .../mybot_sdk/mybot/src/platform/mybot_lcd.c | 11 -- .../mybot_sdk/mybot/src/rtc/mybot_agora_rtc.c | 145 +---------------- .../mybot/src/service/mybot_device_client.c | 14 +- .../mybot/src/support/mybot_http_client.c | 147 +----------------- .../mybot/src/support/mybot_http_header.c | 16 ++ .../mybot/src/support/mybot_ringbuf.c | 10 -- .../mybot_sdk/mybot/src/support/mybot_url.c | 106 +++++++++++++ docs/CORES3_UI.md | 41 ++--- docs/CORES3_UI.zh-CN.md | 32 ++-- docs/PLATFORM_UI.md | 12 +- docs/PLATFORM_UI.zh-CN.md | 11 +- tests/cores3_pixel_ui/README.md | 5 +- tests/cores3_pixel_ui/test_adapter.cc | 86 +++------- 41 files changed, 316 insertions(+), 794 deletions(-) create mode 100644 components/mybot_stack/mybot_sdk/mybot/src/internal/mybot_url.h create mode 100644 components/mybot_stack/mybot_sdk/mybot/src/support/mybot_http_header.c create mode 100644 components/mybot_stack/mybot_sdk/mybot/src/support/mybot_url.c diff --git a/CHANGELOG.md b/CHANGELOG.md index 7ef8d2b..627a28c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,8 +11,7 @@ Versioning and Conventional Commits. profiles, with a linked board documentation index. - 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. @@ -75,6 +74,9 @@ Versioning and Conventional Commits. ### Changed +- 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 @@ -158,8 +160,8 @@ Versioning and Conventional Commits. - 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. + buffers also require CPU, internal-memory, and concurrent-audio measurements. Conversation + transcripts 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 diff --git a/THIRD_PARTY_NOTICES.md b/THIRD_PARTY_NOTICES.md index 3916031..942e0f4 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 | | --- | --- | --- | -| mybot SDK 1.3.0 + post-release updates (`3f9a1ad`) | Apache-2.0; bundled JSON parser portions MIT | `components/mybot_stack/mybot_sdk/mybot` | +| mybot SDK 1.3.0 + post-release updates (`baf41ba`) | 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` | diff --git a/VENDORED_SOURCES.md b/VENDORED_SOURCES.md index 0f1360b..448d0fa 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` | `github.com/junlon2006/mybot` | v1.3.0 + post-release updates, commit `3f9a1add55f1b946d59655b5b88f4662d780fb31` | +| `components/mybot_stack/mybot_sdk/mybot` | `github.com/junlon2006/mybot` | v1.3.0 + post-release updates, commit `baf41bac3b6ca25bad9820f9fc857c94698607d8` | | `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` | 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/drivers/display/renderers/lvgl/PIXEL_GLASSES_SOURCES.md b/components/mybot_platform/src/drivers/display/renderers/lvgl/PIXEL_GLASSES_SOURCES.md index ea3d7cd..f46edac 100644 --- a/components/mybot_platform/src/drivers/display/renderers/lvgl/PIXEL_GLASSES_SOURCES.md +++ b/components/mybot_platform/src/drivers/display/renderers/lvgl/PIXEL_GLASSES_SOURCES.md @@ -49,10 +49,10 @@ and both banks remain valid for the view's lifetime. The view owns one LVGL timer, stopped and deleted before its widgets on destruction. All 23 simulator expressions are retained. The platform's independent -expression policy owns SDK phases, opening expression and MCP hold/replay -timing; the renderer owns only their drawing. State/VP changes update the -third terminal row without restarting a selected expression. No reset, -motor-control or backend-protocol implementation is imported into the view. +expression policy maps SDK phases and the opening expression; the renderer owns +only their drawing. State/VP changes update the third terminal row without +restarting the opener hold. No reset, motor-control or backend-protocol +implementation is imported into the view. ## Masks and fonts 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 5f66c96..8ccd87c 100644 --- a/components/mybot_stack/mybot_sdk/mybot/CHANGELOG.md +++ b/components/mybot_stack/mybot_sdk/mybot/CHANGELOG.md @@ -7,6 +7,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 e52c717..622bc2a 100644 --- a/components/mybot_stack/mybot_sdk/mybot/THIRD_PARTY_NOTICES.md +++ b/components/mybot_stack/mybot_sdk/mybot/THIRD_PARTY_NOTICES.md @@ -24,6 +24,10 @@ Location: `third_party/agora_rtsa_sdk`. The bundled shared-library package ident Linux **development and demo** use only and is intentionally retained in this repository for the Linux reference demo (it is not removed). +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` @@ -37,9 +41,6 @@ require a separate license from Agora (声网). Release maintainers must retain 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. -Files inside the Agora example tree may carry their own copyright or license headers; those terms -also remain in force. - ## cJSON-derived implementation `src/support/mybot_json.c` and `src/internal/mybot_json.h` are namespaced derivatives of cJSON. 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/CORES3_UI.md b/docs/CORES3_UI.md index 67a5441..bb2eb3e 100644 --- a/docs/CORES3_UI.md +++ b/docs/CORES3_UI.md @@ -9,8 +9,8 @@ profiles retain their existing UI and hardware behavior; see [Platform UI](PLATF This replaces CoreS3's earlier status-card view. Audio, camera/video policy, FT6336 touch gestures, power, pins, PSRAM and partitions retain their board configuration. Short touch still starts or -stops a conversation; a three-second hold still requests Wi-Fi provisioning. The MyBot SDK, -AOSL and Agora RTSA snapshots are unchanged. +stops a conversation; a three-second hold still requests Wi-Fi provisioning. The currently pinned +SDK revision is recorded in [dependency baselines](../VENDORED_SOURCES.md). ## Displayed information @@ -31,33 +31,25 @@ The pairing page directs users to the web console. A six-digit numeric pairing c fixed 32 px font on CoreS3; it does not shrink to fit. Chinese guidance reuses the existing 20 px Source Han Sans subset. That subset covers product UI text, not arbitrary Chinese chat. -## Automatic faces and optional LCD indicators +## Automatic faces -The public LCD interface retains four optional one-shot emotion indicators. The current SDK MCP -path accepts only `audio.set_volume` and `audio.adjust_volume` inside a `message.user` envelope; -it does not emit these emotion indicators. The table describes renderer behavior when indicators -are submitted, as exercised by the LCD adapter host tests. +The SDK exposes listening, thinking, speaking and voice-print status. It no longer exposes +one-shot emotion indicators; MCP device commands are limited to `audio.set_volume` and +`audio.adjust_volume`. The renderer keeps the full artwork set for its automatic state mapping. -| State or submitted LCD indicator | Face and hold | +| State | Face and hold | | --- | --- | | READY / return from a conversation | NEUTRAL | | Enter a conversation | SURPRISED for 300 ms, plus entering transition | | LISTENING | LISTENING | | THINKING | THINKING; PROCESSING after three continuous seconds | | SPEAKING / no active phase | NEUTRAL | -| `MYBOT_LCD_INDICATOR_HAPPY` | HAPPY for 2000 ms | -| `MYBOT_LCD_INDICATOR_SAD` | SAD for 3000 ms | -| `MYBOT_LCD_INDICATOR_ANGRY` | ANNOYED for 1200 ms | -| `MYBOT_LCD_INDICATOR_SURPRISED` | SURPRISED for 800 ms | With animations enabled, each entering transition adds 250 ms before its hold, including the -conversation opener. With animations disabled, only the hold remains. Each submitted emotion -indicator replaces the unfinished foreground and replays even the same expression name. -Ordinary phase/voiceprint updates do not restart the hold. -Expiry restores the latest automatic face, including PROCESSING if thinking has continued for -three seconds in the background. Leaving a conversation or detaching the SDK cancels its -expression timers. Operational guidance takes precedence. All expressions are LCD-only and send -no motor commands. +conversation opener. With animations disabled, only the hold remains. Ordinary phase or +voice-print updates do not restart the hold. Leaving a conversation or detaching the SDK cancels +its expression timers. Operational guidance takes precedence. All expressions are LCD-only and +send no motor commands. The complete artwork set contains 23 names: @@ -67,10 +59,10 @@ SURPRISED, SHY, PROUD, LOVE, SLEEPY, BORED, SAD, PLEADING, APOLOGY, WORRIED, ANNOYED, REFUSE, PROCESSING, ERROR, SLEEP ``` -GREETING and the other prepared artwork remain available without automatic demo cycling. +GREETING and the other prepared artwork remain in the renderer without automatic demo cycling. ERROR and SLEEP artwork do not enter an SDK error state or put the board to sleep. The CoreS3 -adapter owns expression timing alongside its existing copied LCD-state submissions; rendering -stays in the existing LVGL task, without an extra UI thread or UTC dependency. +adapter owns automatic expression timing alongside its existing copied LCD-state submissions; +rendering stays in the existing LVGL task, without an extra UI thread or UTC dependency. ## Theme and animation settings @@ -151,9 +143,8 @@ input paths. They do not validate this new pixel renderer. Real-device testing r - Check all ten guidance screens and 23 expressions in both languages on the 320 × 240 panel. - Verify four separate terminal rows, the signature and full-size six-digit pairing codes. -- Verify the SURPRISED opener, phase changes and three-second thinking timeout. Inject optional - LCD emotion indicators to test replacement, same-indicator replay and expiry; phase/voiceprint - updates must preserve hold timing. The SDK MCP path cannot trigger these expression tests. +- Verify the SURPRISED opener, phase changes and three-second thinking timeout. Phase and + voice-print updates must preserve the opener hold timing. - Test animation enabled/disabled, overflowing SSID/instructions, and web-console pairing. - Regress short touch, three-second provisioning, Wi-Fi recovery and repeated SDK stop/start. - Run full-duplex audio with video off and with the existing 1 fps camera uplink enabled. diff --git a/docs/CORES3_UI.zh-CN.md b/docs/CORES3_UI.zh-CN.md index 3ecdc79..0daf530 100644 --- a/docs/CORES3_UI.zh-CN.md +++ b/docs/CORES3_UI.zh-CN.md @@ -8,8 +8,8 @@ CoreS3 LVGL适配器及公共LCD视图接口。不增加手工渲染器开关, [平台UI](PLATFORM_UI.zh-CN.md)。 本视图替换CoreS3旧状态卡片。音频、摄像头/视频策略、FT6336触摸手势、电源、引脚、PSRAM -和分区仍采用原板级配置;短触开始/结束会话、长按三秒配网保持。MyBot SDK、AOSL与Agora -RTSA快照不变。 +和分区仍采用原板级配置;短触开始/结束会话、长按三秒配网保持。当前固定的SDK版本记录于 +[依赖基线](../VENDORED_SOURCES.md)。 ## 显示内容 @@ -25,29 +25,22 @@ RTSA快照不变。 配对页提示在网页控制台输入配对码。CoreS3六位数字配对码固定使用32 px字体,不缩小适配。 中文引导复用原20 px思源黑体子集,字形覆盖产品文案,不覆盖任意中文聊天正文。 -## 自动表情与可选LCD指示 +## 自动表情 -公共LCD接口保留四种可选的一次性情绪指示。当前SDK MCP通路仅接受`message.user`封装内的 -`audio.set_volume`与`audio.adjust_volume`,不产生这些情绪指示。下表描述提交指示时的 -渲染器行为,LCD适配器宿主测试通过直接提交指示验证。 +SDK公开聆听、思考、说话及声纹状态,不再提供一次性情绪指示;MCP设备命令仅支持 +`audio.set_volume`与`audio.adjust_volume`。渲染器保留完整图案集,用于自动状态映射。 -| 状态或提交的LCD指示 | 表情与保持时间 | +| 状态 | 表情与保持时间 | | --- | --- | | READY / 挂断返回 | NEUTRAL | | 进入会话 | SURPRISED保持300 ms,另计进入过渡 | | LISTENING | LISTENING | | THINKING | THINKING;连续三秒后PROCESSING | | SPEAKING / 无阶段 | NEUTRAL | -| `MYBOT_LCD_INDICATOR_HAPPY` | HAPPY,2000 ms | -| `MYBOT_LCD_INDICATOR_SAD` | SAD,3000 ms | -| `MYBOT_LCD_INDICATOR_ANGRY` | ANNOYED,1200 ms | -| `MYBOT_LCD_INDICATOR_SURPRISED` | SURPRISED,800 ms | 开启动画时,每次保持另加250 ms进入过渡,会话开场同样另计;关闭动画时只有保持时间。 -每次提交情绪指示都会替换未结束的前景,重复提交同一指示也会重播。 -普通阶段/声纹更新不重置保持计时,到期恢复最新自动表情;后台思考已满三秒时恢复 -PROCESSING。离开会话或SDK解挂会清除表情计时,必要引导优先。全部表情仅控制LCD, -不发送电机命令。 +普通阶段或声纹更新不重置保持计时。离开会话或SDK解挂会清除表情计时,必要引导优先。 +全部表情仅控制LCD,不发送电机命令。 完整23表情如下: @@ -57,9 +50,9 @@ SURPRISED, SHY, PROUD, LOVE, SLEEPY, BORED, SAD, PLEADING, APOLOGY, WORRIED, ANNOYED, REFUSE, PROCESSING, ERROR, SLEEP ``` -GREETING及其余预置图案保留,不自动演示轮播。ERROR和SLEEP图案不改变SDK运行状态,也不 -使设备休眠。CoreS3适配器在原有复制投递LCD状态流程中维护表情计时,现有LVGL任务渲染, -不新增UI线程或UTC时钟依赖。 +GREETING及其余图案保留在渲染器中,不自动演示轮播。ERROR和SLEEP图案不改变SDK运行状态, +也不使设备休眠。CoreS3适配器在原有复制投递LCD状态流程中维护自动表情计时,现有LVGL任务 +渲染,不新增UI线程或UTC时钟依赖。 ## 主题与动画 @@ -129,8 +122,7 @@ zh-CN耗时38秒、en-US耗时37秒,总计1分16秒。这是构建验证,不 - 在320 × 240屏上检查两种语言、十种引导页面及23个表情。 - 检查四行独立终端、签名及固定大号六位配对码。 -- 验证SURPRISED开场、阶段变化、三秒思考超时;注入可选LCD情绪指示,检查替换、同一指示 - 重播及保持到期,阶段/声纹更新不得重置保持计时。SDK MCP通路不能触发这些表情测试。 +- 验证SURPRISED开场、阶段变化、三秒思考超时;阶段和声纹更新不得重置开场保持计时。 - 开关动画,检查超宽SSID/提示滚动及网页控制台配对。 - 回归短触、三秒配网、断网恢复和反复SDK启停。 - 视频关闭及原1 fps摄像头上行开启时分别验证全双工音频。 diff --git a/docs/PLATFORM_UI.md b/docs/PLATFORM_UI.md index a818671..ab3579d 100644 --- a/docs/PLATFORM_UI.md +++ b/docs/PLATFORM_UI.md @@ -43,15 +43,13 @@ CoreS3 alone uses the fixed process-gray skin, 23 expressions and four terminal text and a 10 px signature. Six-digit numeric pairing codes remain 32 px. READY shows NEUTRAL; entering a conversation shows SURPRISED for 300 ms plus its entering transition. LISTENING and THINKING select their faces, continuous THINKING becomes PROCESSING after three seconds, and -SPEAKING/no phase uses NEUTRAL. Four optional one-shot LCD emotion indicators temporarily override -the face and replay on each submission, with 2000/3000/1200/800 ms holds plus a 250 ms enabled -entering transition. The current SDK MCP path accepts only `audio.set_volume` and -`audio.adjust_volume` inside a `message.user` envelope; it does not emit emotion indicators. -These are LCD-only changes. See [CoreS3 UI](CORES3_UI.md) for timing, resources and validation. +SPEAKING/no phase uses NEUTRAL. The current SDK no longer exposes one-shot emotion indicators; +MCP device commands are limited to `audio.set_volume` and `audio.adjust_volume`. These are +LCD-only changes. See [CoreS3 UI](CORES3_UI.md) for timing, resources and validation. CoreS3's legacy light-theme setting is retained but does not change the pixel skin. Its animation -option controls expression motion and transitions; disabling it retains state/hold progression -and necessary guidance scrolling. The other twelve profiles retain their existing UI/hardware; +option controls expression motion and transitions; disabling it retains the opener hold and +necessary guidance scrolling. The other twelve profiles retain their existing UI/hardware; SDK, AOSL, RTSA, camera/video policy, input, power and memory configuration are unchanged. ## Shared workflow view on other display boards diff --git a/docs/PLATFORM_UI.zh-CN.md b/docs/PLATFORM_UI.zh-CN.md index dcf31f3..836b8ca 100644 --- a/docs/PLATFORM_UI.zh-CN.md +++ b/docs/PLATFORM_UI.zh-CN.md @@ -39,14 +39,13 @@ AMOLED 2.16 使用零 panel gap 与 40 MHz QSPI;CO5300 传输区域两个方 仅CoreS3使用固定工艺灰皮肤、23表情及四行终端,正文9 px、签名10 px,六位数字配对码 固定32 px。READY为NEUTRAL;进入会话SURPRISED保持300 ms并另计进入过渡。LISTENING、 THINKING显示对应表情,连续思考三秒后转PROCESSING,SPEAKING/无阶段时NEUTRAL。 -四种可选的一次性LCD情绪指示临时覆盖当前图案,每次提交都会重播,分别保持 -2000/3000/1200/800 ms;开启动画时另加250 ms进入过渡。当前SDK MCP通路仅接受 -`message.user`封装内的`audio.set_volume`与`audio.adjust_volume`,不产生情绪指示。 -仅控制LCD,具体规则、资源与验证见[CoreS3 UI](CORES3_UI.zh-CN.md)。 +当前SDK不再提供一次性情绪指示,MCP设备命令仅支持`audio.set_volume`与 +`audio.adjust_volume`。仅控制LCD,具体规则、资源与验证见 +[CoreS3 UI](CORES3_UI.zh-CN.md)。 CoreS3保留浅色主题字段兼容但不改变像素皮肤;动画开关控制表情运动/切换,关闭后仍推进 -状态与保持到期,并保留必要的引导文字滚动。其他十二个profile保留原UI/硬件;SDK、AOSL、 -RTSA、摄像头/视频策略、输入、电源及内存配置不变。 +开场保持并保留必要的引导文字滚动。其他十二个profile保留原UI/硬件;摄像头/视频策略、 +输入、电源及内存配置不变。 ## 其他带屏板型的共享流程视图 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"); } From 273e76e37dc0ae38bbd3249ee2d6d106177573a7 Mon Sep 17 00:00:00 2001 From: shangjinlong Date: Fri, 23 Oct 2026 16:06:37 +0800 Subject: [PATCH 2/2] docs: centralize build and validation status --- CHANGELOG.md | 47 ++++------------- CONTRIBUTING.md | 8 +-- CONTRIBUTING.zh-CN.md | 6 +-- README.md | 14 ++---- README.zh-CN.md | 12 ++--- SUPPORT.md | 20 +++----- SUPPORT.zh-CN.md | 15 +++--- components/mybot_platform/boards/README.md | 50 +++++++++++-------- .../boards/atom-echos3r/README.md | 30 +---------- .../boards/bread-compact-wifi-lcd/README.md | 24 +-------- .../mybot_platform/boards/esp-vocat/README.md | 31 +----------- .../esp32-s3-touch-amoled-1.75/README.md | 29 +---------- .../esp32-s3-touch-amoled-1.75c/README.md | 29 +---------- .../esp32-s3-touch-amoled-2.16/README.md | 34 ++----------- .../boards/m5stack-core-s3/README.md | 33 +----------- .../boards/m5stack-stick-s3/README.md | 29 +---------- .../README.md | 30 +---------- .../boards/sensecap-watcher/README.md | 30 ++--------- .../boards/sensecap-watcher/README_en.md | 36 +++---------- .../xingzhi-cube-1.54tft-wifi/README.md | 28 ++--------- .../boards/zhengchen-1.54tft-ml307/README.md | 26 +--------- .../boards/zhengchen-1.54tft-wifi/README.md | 26 +--------- docs/AUDIO_PLAYBACK.md | 8 ++- docs/AUDIO_PLAYBACK.zh-CN.md | 5 +- docs/BOARD_PORTING.md | 14 ++---- docs/BOARD_PORTING.zh-CN.md | 13 ++--- docs/CORES3_AUDIO_TEST.md | 6 +-- docs/CORES3_AUDIO_TEST.zh-CN.md | 4 +- docs/CORES3_UI.md | 13 ++--- docs/CORES3_UI.zh-CN.md | 10 ++-- docs/CORES3_VIDEO.md | 12 ++--- docs/CORES3_VIDEO.zh-CN.md | 7 ++- docs/PLATFORM_UI.md | 23 +++------ docs/PLATFORM_UI.zh-CN.md | 19 +++---- docs/RELEASING.md | 11 ++-- docs/RELEASING.zh-CN.md | 10 ++-- docs/VALIDATION.md | 46 +++++++++++++++++ 37 files changed, 205 insertions(+), 583 deletions(-) create mode 100644 docs/VALIDATION.md diff --git a/CHANGELOG.md b/CHANGELOG.md index 627a28c..8bcfa20 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,8 +7,8 @@ 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. Expressions affect only the LCD. @@ -69,11 +69,14 @@ 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 +- 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. @@ -157,40 +160,8 @@ Versioning and Conventional Commits. ### 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 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 diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 99bcadc..91e3ae1 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 3e88f1e..335b4e1 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 d1cb912..23ecc4d 100644 --- a/README.md +++ b/README.md @@ -115,20 +115,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 ab977bc..72dae4d 100644 --- a/README.zh-CN.md +++ b/README.zh-CN.md @@ -105,18 +105,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/components/mybot_platform/boards/README.md b/components/mybot_platform/boards/README.md index 4c55428..02e6239 100644 --- a/components/mybot_platform/boards/README.md +++ b/components/mybot_platform/boards/README.md @@ -2,10 +2,12 @@ These documents describe the board profiles implemented by `mybot-esp32`. Pins, power sequencing, drivers and build constraints are defined by the checked-in `board.cmake`, `board_config.h` and -`sdkconfig.defaults` files. Use ESP-IDF v5.5.2 and select a board with `MYBOT_BOARD`. +`sdkconfig.defaults` files. Current validation status is centralized in +[`docs/VALIDATION.md`](../../../docs/VALIDATION.md). -以下说明对应本工程已实现的 13 个板型。硬件配置、输入行为、构建约束和验证状态以当前 -板级代码及本工程文档为准。不同尺寸、芯片或硬件版本的板卡不能仅凭外观共用固件。 +以下说明对应本工程已实现的 13 个板型。硬件配置、输入行为和构建约束以当前板级代码为准; +验证状态统一见[验证矩阵](../../../docs/VALIDATION.md)。不同尺寸、芯片或硬件版本的板卡 +不能仅凭外观共用固件。 | Board profile | 板卡说明 | 显示 | 视频 | | --- | --- | --- | --- | @@ -23,38 +25,42 @@ drivers and build constraints are defined by the checked-in `board.cmake`, `boar | `zhengchen-1.54tft-ml307` | [README](zhengchen-1.54tft-ml307/README.md) | ST7789 | 无 | | `zhengchen-1.54tft-wifi` | [README](zhengchen-1.54tft-wifi/README.md) | ST7789 | 无 | -## 构建 +## Build, flash and validation / 构建、烧录与验证 -在工程根目录激活 ESP-IDF v5.5.2,并指定板型: +Activate ESP-IDF v5.5.2 from the repository root: ```sh . /path/to/esp-idf/export.sh test "$(idf.py --version)" = "ESP-IDF v5.5.2" -python3 scripts/build_all.py --board m5stack-core-s3 --language both ``` -脚本默认编译中英文版本,构建目录在 `build/`,合并固件在 `releases/`;常规构建会先清理 -脚本管理的生成目录,增量构建使用 `--no-clean`。仅英文使用 `--language en-US`,仅中文 -使用 `--language zh-CN`。有屏幕的板型自动使用 LVGL;只有 CoreS3 具备视频能力,脚本默认 -开启,音频对照固件可使用 `--video off`。 +Build both languages for one profile: -手动构建时,为每块板指定独立目录和 sdkconfig: +```sh +python3 scripts/build_all.py --board --language both +``` + +The script writes managed builds to `build/` and merged images to `releases/`, derives display +and video capability from the profile, uses the bundled 60 ms RTSA cadence and enables CoreS3 +video by default. Use `--video off` for a no-video comparison. See the +[project README](../../../README.md#build) for root ownership and cleanup rules. + +For a direct build and flash, use a dedicated build directory and port: ```sh -idf.py -B build/m5stack-core-s3 \ - -DMYBOT_BOARD=m5stack-core-s3 \ - -DSDKCONFIG=build/m5stack-core-s3/sdkconfig build -idf.py -B build/m5stack-core-s3 -p PORT flash monitor +idf.py -B build/ \ + -DMYBOT_BOARD= \ + -DSDKCONFIG=build//sdkconfig \ + -DSDKCONFIG_DEFAULTS="sdkconfig.defaults;ci/ptime60.defaults" build +idf.py -B build/ -p PORT flash monitor ``` -手动构建使用当前 sdkconfig 的视频选项;上面的命令不自动开启视频。SenseCAP Watcher 的 -工厂分区保留与烧录步骤见其专用说明。 +Add `ci/en-us.defaults` for English. Add `ci/video.defaults` only when building CoreS3 with +video. SenseCAP Watcher requires the factory-partition backup procedure in its board README. -## 输入、配网与验证 +Board input, provisioning and hardware-specific prerequisites remain in each board README. +Completed build and hardware results are tracked only in the +[validation matrix](../../../docs/VALIDATION.md). 设备首次启动无 Wi-Fi 凭据时自动配网;长按配网输入会先停止 mybot,再进入配网流程, 联网后重新启动 mybot。各板的配网输入、短按/触摸和音量输入见对应 README。 - -文档依据代码描述已实现能力,不代表每块硬件均已实机验证。已有验证记录和限制见 -[平台移植说明](../../../docs/BOARD_PORTING.zh-CN.md),构建/烧录完整说明见 -[中文项目文档](../../../README.zh-CN.md#构建)或 [English guide](../../../README.md#build)。 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 78617cf..5bb0859 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 后才启动 mybot。 -## 构建与烧录 - -在工程根目录激活 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 fb0d82d..d338367 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 7456b54..8636520 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 由板级常驻模块管理,MyBot 停止期间仍可请求配网。 -## 编译与烧录 - -在工程根目录使用 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 3347f59..4c78075 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 由板级常驻模块管理,MyBot 停止期间仍可请求配网。 -## 编译与烧录 - -在工程根目录使用 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 823aa89..1c7585c 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 由板级常驻模块管理,MyBot 停止期间仍可请求配网。 -## 编译与烧录 - -在工程根目录使用 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 c025caf..38c1710 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 信息时自动进入配网并显示热点名称、播放提示音。已有网络时联网后启动 MyBot;长按触摸会先停止 MyBot 再配网。设备音量保存在 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 2af4cb2..0c795be 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 信息时自动进入配网并显示热点名称、 播放提示音;长按主按键会先停止 MyBot 再重新配网。 -## 构建与烧录 - -在仓库根目录使用 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 43204b1..7523668 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 信息时自动创建配置热点并播放提示音;手动配网前先停止 MyBot。 设备没有屏幕,配网与配对状态通过语音和控制台日志查看。 -## 构建与烧录 - -在仓库根目录使用 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 c7bdf49..096b329 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 信息时自动进入配网并显示热点名称、 播放提示音;手动配网前先停止 MyBot。 -## 构建与烧录 +## 出厂数据保护 -在仓库根目录使用 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 273c251..cbae913 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 MyBot 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 d9d380f..58b9f80 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 后才启动 mybot。 -## 构建与烧录 - -在工程根目录激活 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 223c2da..e3bd82b 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 后才启动 mybot。 -## 构建与烧录 - -在工程根目录激活 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 fa39bb2..4649b92 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 后才启动 mybot。 -## 构建与烧录 - -在工程根目录激活 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/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/BOARD_PORTING.md b/docs/BOARD_PORTING.md index 8ad034e..2c600e4 100644 --- a/docs/BOARD_PORTING.md +++ b/docs/BOARD_PORTING.md @@ -88,10 +88,8 @@ Board defaults own Flash, PSRAM, and partition settings. Product-wide settings r `sdkconfig.defaults`; target-wide settings remain in `sdkconfig.defaults.`. The bundled RTSA package supports only 60 ms audio frames. Although menuconfig lists 20 ms and -40 ms, the SDK component wrapper rejects them without a matching RTSA package. The -[CI workflow](../.github/workflows/ci.yml) currently has 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. This is build coverage, not hardware certification. +40 ms, the SDK component wrapper rejects them without a matching RTSA package. See the +[validation matrix](VALIDATION.md) for current build and hardware status. ## Adding a Board @@ -180,7 +178,7 @@ output. Its SDK boundary is 16 kHz mono signed-16 PCM; the physical standard-I2S 32-bit mono left slots. The reference output rate is 24 kHz; add stateful platform resampling only after hardware tests establish it is required. Other panel sizes and shared-clock I2S wiring require separate profiles rather than runtime selection. Chinese and English build support for this -fixed N16R8 profile has been validated with ESP-IDF v5.5.2; real-device validation remains pending. +fixed N16R8 profile is tracked in the [validation matrix](VALIDATION.md). The `esp-vocat` profile supports PCB V1.0 and V1.2 under one compile-time Board because they share the same target, storage, partition, and component configuration. This is runtime hardware-revision @@ -247,13 +245,11 @@ CO5300 QSPI rendering uses the shared LVGL view and a partial RGB565 DMA buffer. 1.75C panels use 466 x 466 with a (6, 0) gap; 2.16 uses 480 x 480, a (0, 0) gap, and 40 MHz QSPI. Every transfer region keeps even start/end pixel boundaries on both axes; no full-screen framebuffer is allocated. CST9217 and Boot input remain Board-owned so either can request provisioning while mybot -is stopped. Each profile is a build target only until power, audio-slot, display, and touch behavior -are verified on its matching release device. +is stopped. Device status is tracked in the [validation matrix](VALIDATION.md). The 2.16 reference uses 24 kHz audio; validate the inherited 16 kHz primary-mic and stereo physical I2S link on real hardware. Keep any required resampling in the platform driver and keep Cloud AEC. Camera, RTC, IMU, TF card, battery reporting, shutdown, and low-power behavior remain unsupported. -Chinese and English firmware build support for 2.16 has been validated with ESP-IDF v5.5.2; -real-device validation remains pending. +Build and device status for 2.16 is tracked in the [validation matrix](VALIDATION.md). The ReSpeaker Flex profile is an example of a hardware audio front end rather than a raw microphone codec. Its XVF3800 must run separately flashed Circular-4 16 kHz, two-channel I2S firmware and owns diff --git a/docs/BOARD_PORTING.zh-CN.md b/docs/BOARD_PORTING.zh-CN.md index d4718c9..228d21b 100644 --- a/docs/BOARD_PORTING.zh-CN.md +++ b/docs/BOARD_PORTING.zh-CN.md @@ -87,9 +87,8 @@ Board defaults 管理 Flash、PSRAM 与分区设置;产品公共设置放在 ` 公共设置放在 `sdkconfig.defaults.`。 随附 RTSA 包只支持 60 ms 音频帧。虽然 menuconfig 仍列出 20 ms 和 40 ms,但在提供匹配的 -RTSA 包前,SDK 构建封装会拒绝这些配置。[CI 工作流](../.github/workflows/ci.yml)当前有 -30 项固件构建:十三个板型分别构建中英文版本,另加 CoreS3 两种语言的视频构建、一个浅色 -主题构建,以及一个关闭会话动画的视频构建。这是构建覆盖,不代表真机验收。 +RTSA 包前,SDK 构建封装会拒绝这些配置。当前构建与真机状态见 +[验证矩阵](VALIDATION.md)。 ## 新增 Board @@ -166,8 +165,7 @@ Board 常驻的 `boards/bread-compact-wifi-lcd/bread_input.c` 只提供 Boot GPI 音量键、触摸、摄像头、GPIO48 LED 或 GPIO18 灯输出。SDK 边界为 16 kHz 单声道 signed-16 PCM,物理标准 I2S 使用 16 kHz、32-bit mono left slot。参考输出为 24 kHz,仅在真机验证 确认必要后增加平台内有状态重采样。其他面板尺寸和共享时钟 I2S 接线应采用独立 profile, -而非运行时切换。该固定 N16R8 profile 的中英文构建支持已在 ESP-IDF v5.5.2 验证,真机 -验证仍未完成。 +而非运行时切换。该固定 N16R8 profile 的构建与真机状态见[验证矩阵](VALIDATION.md)。 `esp-vocat` 在一个编译期 Board profile 中支持 PCB V1.0 与 V1.2,因为两个版本使用相同的 target、存储、分区与 component 配置。这属于运行时硬件版本探测,不是运行时 Board 选择。 @@ -220,11 +218,10 @@ TX 运行以提供 MCLK/BCLK/WS。播放参考输入与本地 AEC 不通过 mybo CO5300 QSPI 使用共享 LVGL 界面与 RGB565 局部 DMA 缓冲。1.75 与 1.75C 为 466 x 466、 (6, 0) panel gap;2.16 为 480 x 480、(0, 0) gap 与 40 MHz QSPI。每次传输两个方向均保持 偶数像素起止边界,不分配完整 framebuffer。CST9217 与 Boot 输入由 Board 常驻持有,使 -mybot 停止期间任一输入仍能请求配网。在各自匹配的发布硬件完成电源、音频 slot、显示和触摸 -验证前,三个 profile 均仅属于构建支持。 +mybot 停止期间任一输入仍能请求配网。真机状态见[验证矩阵](VALIDATION.md)。 2.16 参考音频为 24 kHz,继承的 16 kHz 主麦和双声道物理 I2S 需要真机验证;如需重采样, 应留在平台驱动内,并保持 Cloud AEC。摄像头、RTC、IMU、TF 卡、电量、关机与低功耗尚未支持。 -2.16 中英文固件构建支持已在 ESP-IDF v5.5.2 验证,真机验证仍未完成。 +2.16 的构建与真机状态见[验证矩阵](VALIDATION.md)。 ReSpeaker Flex profile 是硬件音频前端而非原始麦克风 codec 的示例。XVF3800 必须预先单独 烧录 Circular-4 16 kHz 双通道 I2S 固件,并负责 AEC、波束成形、AGC 与降噪。ESP32-S3 diff --git a/docs/CORES3_AUDIO_TEST.md b/docs/CORES3_AUDIO_TEST.md index 643c285..aeea959 100644 --- a/docs/CORES3_AUDIO_TEST.md +++ b/docs/CORES3_AUDIO_TEST.md @@ -23,9 +23,9 @@ with board-specific I2S formatting; see [buffered audio playback](AUDIO_PLAYBACK 16 kHz sample rate, and codec settings remain unchanged. 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 7dc06ce..2ce2553 100644 --- a/docs/CORES3_AUDIO_TEST.zh-CN.md +++ b/docs/CORES3_AUDIO_TEST.zh-CN.md @@ -20,8 +20,8 @@ CoreS3 将 PCM 接收到有界 FIFO,容量为 3,840 个采样点(7,680 字 详见[音频播放缓冲](AUDIO_PLAYBACK.zh-CN.md)。SDK、16 kHz 采样率及 codec 配置保持不变。 预缓冲会增加播放延迟:离线测试后还需验证普通对话、尾音、打断/挂断及 Cloud AEC。 -增加缓冲后的三个阶段已通过 CoreS3 真机听音测试,普通对话在视频开启、关闭两种情况下 -也已验证正常。后续公共缓冲抽取及平台/UI 变化仍需回归,也不能替代其他板型的真机验证。 +当前构建与真机状态统一记录在[验证矩阵](VALIDATION.md)中。本测试结果不能替代其他板型的 +真机验证。 ## 构建与运行 diff --git a/docs/CORES3_UI.md b/docs/CORES3_UI.md index bb2eb3e..8bafe01 100644 --- a/docs/CORES3_UI.md +++ b/docs/CORES3_UI.md @@ -109,7 +109,7 @@ idf.py -B build/cores3-pixel -p flash monitor ``` Use separate sdkconfigs for language, video and animation comparisons; defaults do not overwrite -saved configuration values. Build validation is recorded separately below. +saved configuration values. Current status is tracked in the [validation matrix](VALIDATION.md). ## Rendering, resources and provenance @@ -131,15 +131,10 @@ existing display license. Geometry and colors refer to the user-provided threejs no separate simulator license declaration was found, and this does not assign one. See [dependency baselines](../VENDORED_SOURCES.md) and [third-party notices](../THIRD_PARTY_NOTICES.md). -## Validation status +## Device acceptance checklist -The first Chinese and English CoreS3 builds passed with ESP-IDF v5.5.2 through the standard -builder, using automatic video and 60 ms audio packet time: 38 s for zh-CN, 37 s for en-US, -1 min 16 s for the batch. This is build validation, not a hardware result. Host previews and -device regression remain separate checks. - -Earlier CoreS3 hardware tests cover the previous status-card UI and established audio/camera/ -input paths. They do not validate this new pixel renderer. Real-device testing remains required. +Current build and hardware status is tracked only in the +[validation matrix](VALIDATION.md). The remaining device checks are: - Check all ten guidance screens and 23 expressions in both languages on the 320 × 240 panel. - Verify four separate terminal rows, the signature and full-size six-digit pairing codes. diff --git a/docs/CORES3_UI.zh-CN.md b/docs/CORES3_UI.zh-CN.md index 0daf530..4849da6 100644 --- a/docs/CORES3_UI.zh-CN.md +++ b/docs/CORES3_UI.zh-CN.md @@ -95,7 +95,8 @@ idf.py -B build/cores3-pixel \ idf.py -B build/cores3-pixel -p flash monitor ``` -语言、视频、动画对比使用独立sdkconfig,defaults不会覆盖已保存值;构建验证单独记录于下文。 +语言、视频、动画对比使用独立sdkconfig,defaults不会覆盖已保存值;当前状态见 +[验证矩阵](VALIDATION.md)。 ## 渲染、资源与来源 @@ -113,12 +114,9 @@ alpha数据合计13,631字节,不含描述符。终端字库由DejaVu Sans Mon 视觉/几何参考用户提供的threejs模拟器,未见模拟器独立许可证声明,不为其另行指定许可。 详情见[依赖基线](../VENDORED_SOURCES.md)及[第三方声明](../THIRD_PARTY_NOTICES.md)。 -## 验证状态 +## 真机验收清单 -首轮CoreS3中英文通过ESP-IDF v5.5.2标准脚本构建,自动开启视频、60 ms音频包长: -zh-CN耗时38秒、en-US耗时37秒,总计1分16秒。这是构建验证,不是硬件结果;宿主预览与 -真机回归仍需分别检查。此前CoreS3真机结果属于旧状态卡片及已有音频/摄像头/输入通路, -不代表新像素渲染器通过。仍需完成: +当前构建与真机状态统一记录在[验证矩阵](VALIDATION.md)中。仍需完成: - 在320 × 240屏上检查两种语言、十种引导页面及23个表情。 - 检查四行独立终端、签名及固定大号六位配对码。 diff --git a/docs/CORES3_VIDEO.md b/docs/CORES3_VIDEO.md index bd4f4fe..a4dd126 100644 --- a/docs/CORES3_VIDEO.md +++ b/docs/CORES3_VIDEO.md @@ -82,6 +82,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 @@ -91,14 +95,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 7600117..d6cbe20 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/PLATFORM_UI.md b/docs/PLATFORM_UI.md index ab3579d..30f5cef 100644 --- a/docs/PLATFORM_UI.md +++ b/docs/PLATFORM_UI.md @@ -28,14 +28,11 @@ The AtomEchoS3R and ReSpeaker Flex profiles have no LCD and do not include LVGL. Wi-Fi variants, along with the audio/video protocols, are independent of the display backend. The Xingzhi Cube uses SPI3 mode 3 at 40 MHz, zero offsets, and GPIO13 LEDC backlight with 5 kHz, 13-bit PWM at 60% duty. -Its display and power behavior require real-device validation. Bread Compact Wi-Fi LCD uses SPI3 mode 0 at 40 MHz, zero offsets, RGB order with color inversion, and GPIO42 LEDC backlight at 5 kHz, 13-bit resolution, and 60% duty. It has one Boot input and -uses the shared view at its portrait geometry. Chinese and English build support has been validated; -real-device validation remains pending. +uses the shared view at its portrait geometry. AMOLED 2.16 uses a zero panel gap and 40 MHz QSPI. Its CO5300 transfer regions retain even pixel -boundaries on both axes, and touch/panel orientation must be verified on the physical board. -Chinese and English 2.16 build support has been validated; real-device testing remains pending. +boundaries on both axes. ## CoreS3 pixel-glasses view @@ -100,15 +97,7 @@ sdkconfig when changing defaults, because defaults do not override saved configu ## Validation status -The earlier CoreS3 status-card UI passed real-device testing. The new CoreS3 pixel-glasses view -passed its initial Chinese/English ESP-IDF v5.5.2 standard-builder video builds and still needs -host/real-device validation; previous results do not -validate its layout, expression timing or resource load. The shared-view cleanup, provisioning -SSID display/scrolling and narrow-screen font changes retain their existing regression needs. -CI defines all thirteen profiles in both languages, CoreS3 video in both languages and two -theme/animation variants (30 configurations); that matrix is not a claim that this change has -completed all builds. No new board is claimed to have passed real-device color, touch, audio, -provisioning, or teardown validation. Complete hardware testing must cover all workflow screens, -orientation and colors, Chinese/English small-screen text, SSID and hint scrolling with activity -animation disabled, touch/buttons, Wi-Fi recovery, repeated mybot stop/start, full-duplex audio, -and memory/CPU measurements. +Current build and device status is tracked only in the [validation matrix](VALIDATION.md). +Host adapter tests cover lifecycle, DMA, copied content and teardown behavior. They do not cover +the complete LVGL page rendering, panel behavior or hardware integration; those remain part of +full LVGL page and real-device regression. diff --git a/docs/PLATFORM_UI.zh-CN.md b/docs/PLATFORM_UI.zh-CN.md index 836b8ca..425b8c2 100644 --- a/docs/PLATFORM_UI.zh-CN.md +++ b/docs/PLATFORM_UI.zh-CN.md @@ -25,14 +25,12 @@ AtomEchoS3R 与 ReSpeaker Flex 没有 LCD,不编入 LVGL。ML307、Wi-Fi 及音视频协议与显示后端 相互独立。 行者 Cube 使用 SPI3 mode 3 / 40 MHz、零偏移与 GPIO13 LEDC 背光,PWM 为 5 kHz、13-bit、 -60% 占空比;显示和电源行为仍需 -真机验证。 +60% 占空比。 Bread Compact Wi-Fi LCD 使用 SPI3 mode 0 / 40 MHz、零偏移、RGB 顺序和颜色反转,以及 GPIO42 LEDC 背光(5 kHz、13-bit、60% 占空比)。仅有一个 Boot 输入,共享界面按竖屏尺寸 -布局;中英文构建支持已验证,真机验证仍未完成。 +布局。 AMOLED 2.16 使用零 panel gap 与 40 MHz QSPI;CO5300 传输区域两个方向均保持偶数像素 -边界,触摸和面板方向必须在实际板卡上验证。 -2.16 中英文构建支持已验证,真机测试仍未完成。 +边界。 ## CoreS3像素眼镜视图 @@ -90,11 +88,6 @@ defaults不会覆盖已有保存值。 ## 验证状态 -此前CoreS3状态卡片UI已通过真机测试;新像素眼镜已通过首轮中英文ESP-IDF v5.5.2标准脚本 -视频构建,仍需宿主检查与真机验收。旧结果不能证明新排版、表情时序或资源负载通过。共享视图清理、配网热点名称/ -滚动和窄屏字体仍保留既有回归要求。 -CI定义十三板型中英文、CoreS3视频中英文及主题/动画变体,共30配置;矩阵定义不代表本次 -修改已完成全部构建,更不代表新增板型已经通过真机颜色、 -触摸、音频、配网或销毁验证。真机验收需覆盖所有流程页、方向与颜色、小屏中英文、 -关闭状态动画时的热点名称/提示滚动、触摸/按键、Wi-Fi 恢复、反复 mybot 停止/启动、 -全双工音频及 CPU/内存测量。 +当前构建与真机状态统一记录在[验证矩阵](VALIDATION.md)中。宿主适配器测试覆盖生命周期、 +DMA、内容复制和销毁行为,但不覆盖完整 LVGL 页面渲染、面板行为或硬件集成;这些仍需完整 +LVGL 页面渲染检查和真机回归。 diff --git a/docs/RELEASING.md b/docs/RELEASING.md index 98a9b72..de321f5 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 MyBot 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 449169c..e5196f8 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` 中的 MyBot 快照、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..0e3ab87 --- /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, host test or + simulator preview 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 应链接到这里,不再复制验证状态。