Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 6 additions & 2 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,11 @@ ctest --test-dir build --output-on-failure --no-tests=error --timeout 180 # ne
3. **`modules/*/include/` is the public API; `src/` is not** — but the host build puts
iot-client's `src/` on the *PUBLIC* include path, so app code that includes a private header
compiles here and fails on ESP-IDF (two shipped demos do this). To expose something, promote
the declaration into `iot_client.h` with `IOT_API`.
the declaration into `iot_client.h` with `IOT_API`. The `*_config_defaults.h` knob-default
sheets are the one deliberate exception: they sit on the public include path because they
are integration config surface (integrators derive buffer sizes from the `AGENTIC_KIT_*`
defaults; the ESP-IDF component compiles against that path), but they are not API — the
stable names are the knobs themselves, not the files' contents.
4. **Every new `.c` goes in two source lists**: the root `CMakeLists.txt` and `AK_SRCS` in
`examples/esp-idf/components/agentic_kit/CMakeLists.txt`. No CI job runs `idf.py`, so an
omission is invisible until someone flashes a board. They diverge on purpose — `pal_posix.c`
Expand Down Expand Up @@ -298,7 +302,7 @@ ordinary changes.
leaving both NULL is not "use the system trust store" (there is none on an embedded target),
it connects with verification disabled behind one `log_warn`.
- **`iot_client_process(client, timeout_ms)` ignores `timeout_ms`.** The real blocking budget is
the compile-time `MQTT_RECV_TIMEOUT_MS` (1000 ms), and the CONNECT sets a 60 s keepalive. Do
the compile-time `AGENTIC_KIT_MQTT_RECV_TIMEOUT_MS` (1000 ms), and the CONNECT sets a 60 s keepalive. Do
not use the argument to pace the app loop.
- **`iot_client_connect()` never refreshes the CA and never retries.** The app owns cert
recovery: on `OPRT_TLS_HANDSHAKE_FAILED`, call `iot_get_ca_certificate()` and reassign
Expand Down
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

### Changed

- SDK-wide — every build-time knob is renamed with an `AGENTIC_KIT_` prefix and its default moves to its owning subsystem's config file; override per product with one `agentic_kit_config.h` on the include path, `-D<NAME>=<value>`, or `AGENTIC_KIT_USER_CONFIG` (#38).
- **BREAKING** `TAI_FRAG_BUF_SIZE` → `AGENTIC_KIT_TAI_FRAG_BUF_SIZE`, `RESPONSE_BUFFER_SIZE` → `AGENTIC_KIT_RESPONSE_BUFFER_SIZE`, and likewise the rest — old→new table in `docs-site/docs/guides/compile-time-knobs.md`.
- Knob defaults live at: the override pickup in `common/log.h`; PAL task sizing in `pal/pal_config_defaults.h`; per-module knobs in each module's include/ (`iot_client_config_defaults.h`, `tai_config_defaults.h`; tuya-ble has no knobs, so no defaults file until one appears). Non-knob module data (version strings, endpoints, log binding) lives in each module's src-side internal header (`src/iot_internal.h` restores and renames the former `iot_config_defaults.h`).
- Removed the dead `IOT_DO_NOT_USE_CUSTOM_CONFIG` flag from the ESP-IDF component.
- tuya-ble — the SDK-internal log-facade binding, scan-token rotation and pending-credential
delivery are each defined once in `tuya_ble_internal.h` instead of being repeated per module (PR pending).
- tuya-ble — bounded per-state Trsmitr reassembly, queued TX with backpressure, and configurable radio capability (#35).
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ cmake --build build-examples

## 版本与发布

SDK 版本定义在 `modules/iot-client/src/iot_config_defaults.h` 的 `SDK_VERSION` 宏中,有两种状态(类似 maven 的 release / `-SNAPSHOT`):
SDK 版本定义在 `modules/iot-client/include/iot_client_config_defaults.h` 的 `SDK_VERSION` 宏中,有两种状态(类似 maven 的 release / `-SNAPSHOT`):

- `agentic-kit_X.Y.Z` — 已发布状态(该值对应 `vX.Y.Z` 标签)
- `agentic-kit_X.Y.Z-dev` — 开发周期状态
Expand Down
2 changes: 1 addition & 1 deletion common/core_mqtt_config.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@
/* coreMQTT invokes these with a doubly-parenthesised argument --
* LogError( ( "fmt", args ) ) -- so `message` arrives complete with its own
* parentheses, which then serve as the call parentheses of the macro below.
* Same shape as the log_* wrappers in iot_config_defaults.h. */
* Same shape as the log_* wrappers in iot_client_config_defaults.h. */
#define CORE_MQTT_LOG_ERROR( ... ) log_emit(LOG_ERROR, "[mqtt] " __VA_ARGS__)
#define CORE_MQTT_LOG_WARN( ... ) log_emit(LOG_WARN, "[mqtt] " __VA_ARGS__)

Expand Down
54 changes: 54 additions & 0 deletions common/log.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,60 @@
#include <stdarg.h>
#include <stddef.h>

/* -------------------------------------------------------------------------
* Build-time config: the integrator-override pickup. Every SDK subsystem
* keeps its knob defaults in its own *_config_defaults.h
* (modules/<m>/include/, pal/pal_config_defaults.h); the one thing they
* all share is this header, because every SDK translation unit includes
* it. That makes log.h the right home for the override pickup: it must
* run BEFORE any #ifndef knob default, whichever file that default lives
* in -- and each defaults file includes this header first for exactly
* that reason.
*
* Integrators override by defining a knob FIRST -- pick whichever fits the
* build system (all of them must apply to every target that compiles SDK
* sources, so no translation unit sees a different value):
* 1. Create your own agentic_kit_config.h holding only the knobs you
* want to change (plain #define, no #ifndef), and put its directory
* on the include path (-I / target_include_directories). It is
* picked up automatically, before every default.
* 2. Add -D<NAME>=<value> to the compile options.
* 3. -DAGENTIC_KIT_USER_CONFIG='"my_kit_opts.h"' names an override
* header with an arbitrary file name (its directory still needs
* to be on the include path) -- for toolchains without __has_include.
* When set, it wins and the agentic_kit_config.h search is skipped.
*
* Why the SDK never owns a file named agentic_kit_config.h: a quoted
* include (and __has_include with quotes) searches the includer's own
* directory (common/) BEFORE the -I path, so an SDK-owned
* common/agentic_kit_config.h could never be shadowed by an integrator's
* same-named file. Reserving that name for the integrator is the whole
* trick (lwIP lwipopts.h / mbedTLS mbedtls_config.h / FreeRTOS
* FreeRTOSConfig.h pattern).
*
* All SDK knobs are prefixed AGENTIC_KIT_ to keep them out of the
* integrator's namespace (coreMQTT's own core_mqtt_config_defaults.h
* defines a same-named MQTT_SEND_TIMEOUT_MS that collided for real).
* Tables, per-knob rationale and migration live in
* docs-site/docs/guides/compile-time-knobs.md.
*
* The pickup runs BEFORE the extern "C" opener: it pulls in the
* integrator's override header, and a C++ translation unit's config must
* not silently acquire C linkage.
* ------------------------------------------------------------------------- */

/* Integrator overrides come first, so every #ifndef knob default -- here
* and in every *_config_defaults.h -- loses to them. */
#ifdef AGENTIC_KIT_USER_CONFIG
#include AGENTIC_KIT_USER_CONFIG
#else
#if defined(__has_include)
#if __has_include("agentic_kit_config.h")
#include "agentic_kit_config.h"
#endif
#endif
#endif

#ifdef __cplusplus
extern "C" {
#endif
Expand Down
2 changes: 1 addition & 1 deletion docs-site/docs/guides/atop-generic-call.md
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,7 @@ iot_atop_response_free(client, &resp); /* 每条路径都要调,包括失败

**只支持已激活的设备。** 通用入口用 `devid` + `secret_key` 签名。激活本身用的是 `uuid` + `authkey`,是另一条路径,仍然只能通过 `iot_client_init_on_boarding()` 走。在没有凭据的 client 上调用返回 `OPRT_UNINITIALIZED`。

**单次响应不能超过 4096 字节,连 HTTP 头一起算。** 状态行、响应头和加密后的响应体共用一个固定大小的缓冲区(`RESPONSE_BUFFER_SIZE`,`http_client_interface.c`),没有分段续读。溢出时底层 coreHTTP 返回 `HTTPInsufficientMemory`,SDK 把它折叠成 `OPRT_COMMUNICATION_ERROR`——和"socket 断了"是同一个返回值,而 coreHTTP 自己的解释性日志在本项目里被编译掉了(`HTTP_DO_NOT_USE_CUSTOM_CONFIG`),所以现场只看得到一次"传输层失败",重试也不会好。扣掉响应头、base64 膨胀和信封字段,**解密后 JSON 的实际上限约 2.8 KB**。返回定长字段的接口绰绰有余;返回列表、DP schema 这类长度随产品增长的接口很容易撞上——遇到这种接口请提 issue,把它变成具名接口的同一个改动里需要把这个常量一起抬上去。
**单次响应不能超过 4096 字节,连 HTTP 头一起算。** 状态行、响应头和加密后的响应体共用一个固定大小的缓冲区(`AGENTIC_KIT_RESPONSE_BUFFER_SIZE`,默认值与调整说明见 `modules/iot-client/include/iot_client_config_defaults.h`),没有分段续读。溢出时底层 coreHTTP 返回 `HTTPInsufficientMemory`,SDK 把它折叠成 `OPRT_COMMUNICATION_ERROR`——和"socket 断了"是同一个返回值,而 coreHTTP 自己的解释性日志在本项目里被编译掉了(`HTTP_DO_NOT_USE_CUSTOM_CONFIG`),所以现场只看得到一次"传输层失败",重试也不会好。扣掉响应头、base64 膨胀和信封字段,**解密后 JSON 的实际上限约 2.8 KB**。返回定长字段的接口绰绰有余;返回列表、DP schema 这类长度随产品增长的接口很容易撞上——遇到这种接口请提 issue,把它变成具名接口的同一个改动里需要把这个常量一起抬上去。

**请求体原样透传。** SDK 不会改写你的请求体,所以接口要求的字段必须自己带齐——**包括大多数 ATOP 接口在请求体里要求的 `t` 时间戳字段**。SDK 只校验到"能解析成 JSON 对象"为止,目的是把手误变成一个立刻返回的 `OPRT_INVALID_PARAMETER`,而不是花一次 HTTPS 往返换一句含义模糊的云端拒绝。

Expand Down
Loading
Loading