diff --git a/CHANGELOG.md b/CHANGELOG.md index 51eb1fe..3c1e2f3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -15,19 +15,26 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 (v4.4), `tuya.device.versions.update` (v4.1), and `tuya.device.upgrade.status.update` (v4.1). - `iot_ota_report_version` — reports the device's current firmware version - (also auto-called during `iot_client_init`, so the cloud can evaluate - upgrades). + (auto-called during `iot_client_init` from `iot_client_config_t.sw_ver`, so + the cloud can evaluate upgrades against the running version). - `iot_ota_check_upgrade` — queries the cloud for a pending upgrade and returns version, download URL (`cdnUrl` preferred, `httpsUrl` fallback), - file size, and MD5/HMAC hashes. + file size, and MD5/HMAC hashes. Takes no `sw_ver` argument — the cloud + compares against the version already reported at init. - `iot_ota_report_status` — drives the upgrade lifecycle (UPGRADING → FINI / EXEC / ABORT). + - **Application-supplied firmware version.** `iot_client_config_t.sw_ver` and + `iot_on_boarding_config_t.sw_ver` let the app report its own version + (`NULL` = SDK default `IOT_SDK_SW_VER`); `IOT_SDK_SW_VER` / `IOT_SDK_PV` / + `IOT_SDK_BV` are now `#ifndef`-guarded so they can also be overridden at + compile time. - The SDK handles **only the cloud protocol**; the application owns download and flash (e.g. ESP-IDF `esp_ota_*` or a vendor bootloader API). - `atop_base` gains an AES-128-ECB fallback decrypt path for older (`et=1`) cloud responses. - Unit tests with mocked ATOP endpoints (`iot_ota_test`), a POSIX `ota-demo`, - and an ESP-IDF `ota-demo` with a two-partition OTA table. + and an ESP-IDF `ota-demo` with dual 4 MB OTA partitions on 16 MB flash + (sized for ~4 MB firmware images). ### Changed diff --git a/README.md b/README.md index 98af12f..eb1af38 100644 --- a/README.md +++ b/README.md @@ -8,6 +8,7 @@ - 图片理解与生成 - 设备侧 MCP(Model Context Protocol)支持 - 设备数据点(DP)管理:schema 校验、本地缓存、批量上报、下行回调、状态持久化 +- OTA 固件升级:云端协议(版本上报 / 升级检查 / 状态回报),下载与烧录由应用负责 - 芯片和操作系统无关:macOS、Linux、FreeRTOS (ESP32)、MIPS、ARM - 全球化部署,支持多数据中心区域 @@ -17,7 +18,7 @@ |------|--------|------| | RTC TCP Client | `tuya_ai.h` | tRTC(tuya自研RTC协议) TCP 实现,开源实现,PAL 可移植 | | RTC Client | `stm_open.h` | tRTC(tuya自研RTC协议) UDP 实现,预编译静态库形式 | -| IoT Client | `iot_client.h`、`iot_dp.h` | 设备激活、MQTT 连接、会话令牌获取;数据点(DP)管理(schema 校验 / 缓存 / 上下行 / 持久化) | +| IoT Client | `iot_client.h`、`iot_dp.h`、`iot_ota.h` | 设备激活、MQTT 连接、会话令牌获取;数据点(DP)管理(schema 校验 / 缓存 / 上下行 / 持久化);OTA 固件升级(云端协议) | | Tuya BLE | `tuya_ble_nimble.h` | BLE 蓝牙配网(ESP-IDF) | ## 环境要求 @@ -64,6 +65,9 @@ cmake --build build # 设备数据点(DP)管理 ./build/dp_management_demo + +# OTA 固件升级(云端协议) +./build/ota_demo ``` ## 项目结构 diff --git a/README_en.md b/README_en.md index 35e3fb5..87ddcb2 100644 --- a/README_en.md +++ b/README_en.md @@ -8,6 +8,7 @@ Multimodal device-side SDK for connecting smart hardware to the Tuya AI platform - Image understanding and generation - Device-side MCP (Model Context Protocol) support - Device data point (DP) management: schema validation, local cache, batch reporting, downlink callbacks, state persistence +- OTA firmware upgrade: cloud protocol (version report / upgrade check / status report); download and flash owned by the application - Platform and chip agnostic: macOS, Linux, FreeRTOS (ESP32), MIPS, ARM - Global deployment with multiple data center regions @@ -15,9 +16,9 @@ Multimodal device-side SDK for connecting smart hardware to the Tuya AI platform | Module | Header | Description | |--------|--------|-------------| -| RTC TCP Client | `tuya_ai.h` | tRTC (Tuya RTC protocol), TCP implementation, fullly open sourced with PAL portability | +| RTC TCP Client | `tuya_ai.h` | tRTC (Tuya RTC protocol), TCP implementation, fully open sourced with PAL portability | | RTC Client | `stm_open.h` | tRTC (Tuya RTC protocol), UDP implementation, pre-compiled static library | -| IoT Client | `iot_client.h`, `iot_dp.h` | Device activation, MQTT, session token; Data Point (DP) management (schema validation / cache / up- & downlink / persistence) | +| IoT Client | `iot_client.h`, `iot_dp.h`, `iot_ota.h` | Device activation, MQTT, session token; Data Point (DP) management (schema validation / cache / up- & downlink / persistence); OTA firmware upgrade (cloud protocol) | | Tuya BLE | `tuya_ble_nimble.h` | BLE provisioning (ESP-IDF) | ## Prerequisites @@ -62,6 +63,9 @@ Then run: # Device data point (DP) management ./build/dp_management_demo + +# OTA firmware upgrade (cloud protocol) +./build/ota_demo ``` ## Project Structure diff --git a/docs-site/docs/guides/ota-upgrade.md b/docs-site/docs/guides/ota-upgrade.md index 72c2016..f6c2690 100644 --- a/docs-site/docs/guides/ota-upgrade.md +++ b/docs-site/docs/guides/ota-upgrade.md @@ -39,8 +39,8 @@ SDK 只提供**云端协议原语**——版本上报、升级查询、状态回 | API | 云端接口 | 用途 | |-----|---------|------| -| `iot_ota_report_version` | `tuya.device.versions.update` (v4.1) | 上报当前固件版本(`iot_client_init` 也会自动调用) | -| `iot_ota_check_upgrade` | `tuya.device.upgrade.get` (v4.4) | 查询是否有待升级固件,返回 URL / 版本 / 大小 / 哈希 | +| `iot_ota_report_version` | `tuya.device.versions.update` (v4.1) | 上报当前固件版本(`iot_client_init` 会用 `iot_client_config_t.sw_ver` 自动调用,NULL 时用 SDK 默认 `IOT_SDK_SW_VER`) | +| `iot_ota_check_upgrade` | `tuya.device.upgrade.get` (v4.4) | 查询是否有待升级固件,返回 URL / 版本 / 大小 / 哈希(云端与已上报的版本比较,不再传版本号) | | `iot_ota_report_status` | `tuya.device.upgrade.status.update` (v4.1) | 回报升级生命周期状态 | ### `iot_ota_check_upgrade` 返回的升级信息 @@ -49,7 +49,7 @@ SDK 只提供**云端协议原语**——版本上报、升级查询、状态回 typedef struct { bool has_upgrade; // 云端是否有升级 char *version; // 目标版本号 - char *url; // 固件下载 URL(HTTPS) + char *url; // 固件下载 URL(优先 cdnUrl,回退 httpsUrl) long file_size; // 固件大小(字节) int channel; // 固件通道(0 = 主 MCU) char *md5; // MD5 校验(可能为 NULL) @@ -77,15 +77,15 @@ typedef enum { ### 1. 分区表 -OTA 需要两个 app 分区(`ota_0` / `ota_1`)和一个 `otadata` 分区。demo 使用的 `partitions.csv`(8MB flash): +OTA 需要两个 app 分区(`ota_0` / `ota_1`)和一个 `otadata` 分区。demo 使用的 `partitions.csv`(16MB flash,每个 app 分区 4MB,可容纳约 4MB 的固件): ```csv # Name, Type, SubType, Offset, Size, Flags nvs, data, nvs, 0x9000, 0x6000, phy_init, data, phy, 0xf000, 0x1000, otadata, data, ota, 0x10000, 0x2000, -ota_0, app, ota_0, 0x20000, 1500K, -ota_1, app, ota_1, , 1500K, +ota_0, app, ota_0, 0x20000, 4M, +ota_1, app, ota_1, , 4M, ``` ### 2. sdkconfig 关键项 @@ -93,8 +93,8 @@ ota_1, app, ota_1, , 1500K, ```ini # 给 TLS + HTTP + esp_ota 留够栈 CONFIG_ESP_MAIN_TASK_STACK_SIZE=16384 -# 8MB flash -CONFIG_ESPTOOLPY_FLASHSIZE_8MB=y +# 16MB flash(容纳双 4MB OTA 分区) +CONFIG_ESPTOOLPY_FLASHSIZE_16MB=y # 自定义分区表 CONFIG_PARTITION_TABLE_CUSTOM=y CONFIG_PARTITION_TABLE_CUSTOM_FILENAME="partitions.csv" @@ -120,12 +120,14 @@ iot_client_config_t iot_cfg = { .env = DEFAULT_ENV, /* mqtt_auto_connect = false: 只用 ATOP HTTP,不连 MQTT */ .mqtt_auto_connect = false, + /* 应用固件版本:init 时自动上报,供云端 OTA 比较(NULL 用 SDK 默认) */ + .sw_ver = desc->version, }; iot_client_t *iot = iot_client_init(&iot_cfg); -/* 查询升级,传入当前版本号供云端比较 */ +/* 查询升级(云端与 init 时上报的 sw_ver 比较,无需再传版本号) */ iot_ota_upgrade_info_t info = {0}; -int rc = iot_ota_check_upgrade(iot, 0, desc->version, &info); +int rc = iot_ota_check_upgrade(iot, 0, &info); if (rc == OPRT_OK && info.has_upgrade) { ESP_LOGI(TAG, "upgrade -> %s url=%s size=%ld", info.version, info.url, info.file_size); diff --git a/docs-site/docs/reference/iot-client.md b/docs-site/docs/reference/iot-client.md index 6875478..eac6103 100644 --- a/docs-site/docs/reference/iot-client.md +++ b/docs-site/docs/reference/iot-client.md @@ -93,6 +93,10 @@ sidebar_position: 3 | `cacert` | `const char *` | CA 证书 PEM(用于 MQTT/HTTPS/IoT-DNS TLS,调用方持有,需在 client 生命周期内有效) | | `cert_bundle_attach` | `tls_cert_bundle_attach_fn` | 平台证书包回调(如 ESP-IDF 的 `esp_crt_bundle_attach`),NULL 表示不使用。详见 [TLS 证书验证](../guides/tls-cert-verification.md) | | `message_callback` | `iot_message_callback_t` | MQTT 消息回调,可为 NULL | +| `schema` | `const char *` | 重启时用于恢复的 DP schema JSON(调用方持有,NULL = 不恢复 / 宽松模式) | +| `schema_id` | `const char *` | 持久化的 schema id(schema 升级查询的稳定 key,可为 NULL) | +| `dp_state` | `const char *` | 持久化的 DP 当前状态 `{"dps":{...}}`,用于恢复(不置脏、不上报,可为 NULL) | +| `sw_ver` | `const char *` | 应用固件版本号(如 `"1.2.3"`),`iot_client_init` 时自动上报供云端 OTA 比较;NULL 表示使用 SDK 默认 `IOT_SDK_SW_VER`。详见 [OTA 升级](../guides/ota-upgrade.md) | ### `iot_on_boarding_config_t` @@ -114,6 +118,7 @@ sidebar_position: 3 | `cacert` | `const char *` | CA 证书 PEM(用于 MQTT/HTTPS/IoT-DNS TLS,调用方持有) | | `cert_bundle_attach` | `tls_cert_bundle_attach_fn` | 平台证书包回调(如 ESP-IDF 的 `esp_crt_bundle_attach`),NULL 表示不使用。详见 [TLS 证书验证](../guides/tls-cert-verification.md) | | `message_callback` | `iot_message_callback_t` | MQTT 消息回调 | +| `sw_ver` | `const char *` | 应用固件版本号(如 `"1.2.3"`),激活后自动上报供云端 OTA 比较;NULL 表示使用 SDK 默认 `IOT_SDK_SW_VER`。详见 [OTA 升级](../guides/ota-upgrade.md) | ### `iot_client_t`(返回实例) diff --git a/examples/esp-idf/ota-demo/README.md b/examples/esp-idf/ota-demo/README.md index fea9ee3..115ac0a 100644 --- a/examples/esp-idf/ota-demo/README.md +++ b/examples/esp-idf/ota-demo/README.md @@ -27,7 +27,7 @@ Demonstrates a complete firmware OTA upgrade flow using the agentic-kit `iot_ota ## Partition Table -Uses a custom partition table (`partitions.csv`) with two 1.5MB OTA partitions (`ota_0`, `ota_1`) on 8MB flash. The binary is ~1.1MB (WiFi + TLS + HTTP + OTA). +Uses a custom partition table (`partitions.csv`) with two 4MB OTA partitions (`ota_0`, `ota_1`) on 16MB flash, sized for firmware images up to ~4MB. The demo binary itself is ~1.1MB (WiFi + TLS + HTTP + OTA). ## How It Works diff --git a/examples/esp-idf/ota-demo/main/main.c b/examples/esp-idf/ota-demo/main/main.c index 8992a69..98eac4e 100644 --- a/examples/esp-idf/ota-demo/main/main.c +++ b/examples/esp-idf/ota-demo/main/main.c @@ -303,6 +303,7 @@ void app_main(void) .schema = NULL, .schema_id = NULL, .dp_state = NULL, + .sw_ver = desc->version, }; memcpy((char *)iot_cfg.devid, DEFAULT_DEVID, strlen(DEFAULT_DEVID)); memcpy((char *)iot_cfg.secret_key, DEFAULT_SECRET_KEY, strlen(DEFAULT_SECRET_KEY)); @@ -317,7 +318,7 @@ void app_main(void) /* 3. Check cloud for firmware upgrade */ iot_ota_upgrade_info_t info = {0}; - int rc = iot_ota_check_upgrade(iot, 0, desc->version, &info); + int rc = iot_ota_check_upgrade(iot, 0, &info); if (rc != OPRT_OK) { ESP_LOGE(TAG, "iot_ota_check_upgrade failed: %d", rc); iot_ota_upgrade_info_free(iot, &info); diff --git a/examples/esp-idf/ota-demo/partitions.csv b/examples/esp-idf/ota-demo/partitions.csv index 49f98a9..3def8c8 100644 --- a/examples/esp-idf/ota-demo/partitions.csv +++ b/examples/esp-idf/ota-demo/partitions.csv @@ -2,5 +2,5 @@ nvs, data, nvs, 0x9000, 0x6000, phy_init, data, phy, 0xf000, 0x1000, otadata, data, ota, 0x10000, 0x2000, -ota_0, app, ota_0, 0x20000, 1500K, -ota_1, app, ota_1, , 1500K, +ota_0, app, ota_0, 0x20000, 4M, +ota_1, app, ota_1, , 4M, diff --git a/examples/esp-idf/ota-demo/sdkconfig.defaults b/examples/esp-idf/ota-demo/sdkconfig.defaults index 789aa72..f382ba8 100644 --- a/examples/esp-idf/ota-demo/sdkconfig.defaults +++ b/examples/esp-idf/ota-demo/sdkconfig.defaults @@ -1,7 +1,7 @@ # OTA needs enough stack for TLS + HTTP + esp_ota writes CONFIG_ESP_MAIN_TASK_STACK_SIZE=16384 CONFIG_MBEDTLS_HKDF_C=y -CONFIG_ESPTOOLPY_FLASHSIZE_8MB=y +CONFIG_ESPTOOLPY_FLASHSIZE_16MB=y CONFIG_PARTITION_TABLE_CUSTOM=y CONFIG_PARTITION_TABLE_CUSTOM_FILENAME="partitions.csv" CONFIG_SPIRAM=y diff --git a/examples/posix/ota-demo/ota_demo.c b/examples/posix/ota-demo/ota_demo.c index 7bf7158..69ef604 100644 --- a/examples/posix/ota-demo/ota_demo.c +++ b/examples/posix/ota-demo/ota_demo.c @@ -98,6 +98,7 @@ int demo_ota_run(const char *devid, const char *secret_key, const char *local_ke .env = PROD, .mqtt_disable_tls = false, .mqtt_auto_connect = false, + .sw_ver = sw_ver, }; strncpy(cfg.devid, devid, sizeof(cfg.devid) - 1); strncpy(cfg.secret_key, secret_key, sizeof(cfg.secret_key) - 1); @@ -108,22 +109,12 @@ int demo_ota_run(const char *devid, const char *secret_key, const char *local_ke fprintf(stderr, "[%s] iot_client_init failed\n", TAG); return -1; } - printf("[%s] client initialized (devid=%s)\n", TAG, client->devid); + printf("[%s] client initialized (devid=%s, sw_ver=%s)\n", TAG, client->devid, sw_ver); - /* 2. Report current firmware version */ - printf("[%s] reporting firmware version: %s\n", TAG, sw_ver); - int rc = iot_ota_report_version(client, sw_ver); - if (rc != OPRT_OK) { - fprintf(stderr, "[%s] iot_ota_report_version failed: %d\n", TAG, rc); - /* non-fatal — continue to upgrade check */ - } else { - printf("[%s] version reported successfully\n", TAG); - } - - /* 3. Check for firmware upgrade */ + /* 2. Check for firmware upgrade */ printf("[%s] checking cloud for firmware upgrade...\n", TAG); iot_ota_upgrade_info_t info = {0}; - rc = iot_ota_check_upgrade(client, 0, sw_ver, &info); + int rc = iot_ota_check_upgrade(client, 0, &info); if (rc != OPRT_OK) { fprintf(stderr, "[%s] iot_ota_check_upgrade failed: %d\n", TAG, rc); iot_ota_upgrade_info_free(client, &info); @@ -138,7 +129,7 @@ int demo_ota_run(const char *devid, const char *secret_key, const char *local_ke return 0; } - /* 4. Print upgrade info */ + /* 3. Print upgrade info */ printf("[%s] ===== firmware upgrade available =====\n", TAG); printf("[%s] version : %s\n", TAG, info.version ? info.version : "?"); printf("[%s] url : %s\n", TAG, info.url); @@ -147,14 +138,14 @@ int demo_ota_run(const char *devid, const char *secret_key, const char *local_ke printf("[%s] md5 : %s\n", TAG, info.md5 ? info.md5 : "(none)"); printf("[%s] hmac : %s\n", TAG, info.hmac ? info.hmac : "(none)"); - /* 5. Report UPGRADING status */ + /* 4. Report UPGRADING status */ printf("[%s] reporting UPGRADING status...\n", TAG); rc = iot_ota_report_status(client, info.channel, OTA_STATUS_UPGRADING); if (rc != OPRT_OK) { fprintf(stderr, "[%s] failed to report UPGRADING: %d\n", TAG, rc); } - /* 6. Optionally download the firmware image */ + /* 5. Optionally download the firmware image */ int result = 0; if (auto_download && info.url) { char out_path[256]; diff --git a/modules/iot-client/include/iot_client.h b/modules/iot-client/include/iot_client.h index eb50442..ce923f0 100644 --- a/modules/iot-client/include/iot_client.h +++ b/modules/iot-client/include/iot_client.h @@ -101,6 +101,7 @@ typedef struct { const char *schema; // Persisted DP schema JSON to restore on restart (NULL = none / loose mode) const char *schema_id; // Persisted schema id (stable key for schema upgrade query) const char *dp_state; // Persisted DP current state {"dps":{...}} to restore (no dirty, no report) + const char *sw_ver; // Application firmware version (e.g. "1.2.3"); NULL = use SDK default IOT_SDK_SW_VER } iot_client_config_t; /** @@ -121,6 +122,7 @@ typedef struct { const char *cacert; // CA cert for all TLS (MQTT/HTTPS/IoT-DNS) (PEM, caller-owned, must outlive client) tls_cert_bundle_attach_fn cert_bundle_attach; // Platform cert-bundle callback (NULL = none) iot_message_callback_t message_callback; // MQTT message callback + const char *sw_ver; // Application firmware version (e.g. "1.2.3"); NULL = use SDK default IOT_SDK_SW_VER } iot_on_boarding_config_t; diff --git a/modules/iot-client/include/iot_ota.h b/modules/iot-client/include/iot_ota.h index 2bd557c..4b376b4 100644 --- a/modules/iot-client/include/iot_ota.h +++ b/modules/iot-client/include/iot_ota.h @@ -97,14 +97,11 @@ OTA_API int iot_ota_report_version(iot_client_t *client, const char *sw_ver); * * @param[in] client IoT client instance (must be initialized) * @param[in] channel Firmware channel (0 = main MCU firmware) - * @param[in] sw_ver Current firmware version string sent to cloud for - * comparison (e.g. "1.0.0"); pass NULL to omit * @param[out] info Output: upgrade info (caller must free with * iot_ota_upgrade_info_free()) * @return OPRT_OK on success (including no-upgrade case), error code on failure */ OTA_API int iot_ota_check_upgrade(iot_client_t *client, int channel, - const char *sw_ver, iot_ota_upgrade_info_t *info); /** diff --git a/modules/iot-client/src/atop.c b/modules/iot-client/src/atop.c index 2a52fe4..0eba1d9 100644 --- a/modules/iot-client/src/atop.c +++ b/modules/iot-client/src/atop.c @@ -746,9 +746,6 @@ int atop_upgrade_get(const pal_t *pal, const ota_upgrade_request_t *request, ota return OPRT_MALLOC_FAILED; } cJSON_AddNumberToObject(root, "type", request->channel); - if (request->sw_ver && request->sw_ver[0] != '\0') { - cJSON_AddStringToObject(root, "softVer", request->sw_ver); - } cJSON_AddNumberToObject(root, "t", (double)timestamp); char *post_data = cJSON_PrintUnformatted(root); diff --git a/modules/iot-client/src/atop.h b/modules/iot-client/src/atop.h index 6e4a157..a375ba4 100644 --- a/modules/iot-client/src/atop.h +++ b/modules/iot-client/src/atop.h @@ -205,7 +205,6 @@ typedef struct { const char *devid; const char *key; int channel; /**< firmware type/channel (0 = main MCU) */ - const char *sw_ver; /**< current firmware version (sent as softVer for server-side comparison) */ const char *host; uint16_t port; const char *cacert; diff --git a/modules/iot-client/src/iot_client.c b/modules/iot-client/src/iot_client.c index b91ae3a..c62ca89 100644 --- a/modules/iot-client/src/iot_client.c +++ b/modules/iot-client/src/iot_client.c @@ -266,7 +266,10 @@ IOT_API iot_client_t *iot_client_init(const iot_client_config_t *config) /* Report firmware version to cloud (enables OTA upgrade checks) */ { - int ret = iot_ota_report_version(client, IOT_SDK_SW_VER); + const char *fw_ver = (config->sw_ver && config->sw_ver[0]) + ? config->sw_ver + : IOT_SDK_SW_VER; + int ret = iot_ota_report_version(client, fw_ver); if (ret != OPRT_OK) { log_warn("iot_ota_report_version failed: %d (non-fatal)", ret); } @@ -322,7 +325,10 @@ IOT_API iot_client_t *iot_client_init_on_boarding(const iot_on_boarding_config_t strncpy(ob_cfg.authkey, config->authkey, sizeof(ob_cfg.authkey) - 1); strncpy(ob_cfg.product_key, config->product_key, sizeof(ob_cfg.product_key) - 1); - strncpy(ob_cfg.sw_ver, IOT_SDK_SW_VER, sizeof(ob_cfg.sw_ver) - 1); + const char *sw_ver = (config->sw_ver && config->sw_ver[0]) + ? config->sw_ver + : IOT_SDK_SW_VER; + strncpy(ob_cfg.sw_ver, sw_ver, sizeof(ob_cfg.sw_ver) - 1); strncpy(ob_cfg.pv, IOT_SDK_PV, sizeof(ob_cfg.pv) - 1); strncpy(ob_cfg.bv, IOT_SDK_BV, sizeof(ob_cfg.bv) - 1); @@ -362,6 +368,7 @@ IOT_API iot_client_t *iot_client_init_on_boarding(const iot_on_boarding_config_t client_config.cacert = config->cacert; client_config.cert_bundle_attach = config->cert_bundle_attach; client_config.message_callback = config->message_callback; + client_config.sw_ver = sw_ver; /* schema / schema_id come from the activation response. iot_client_init() * copies them and rebuilds the DP registry from the schema (dp_state is then * initialized from the schema); first activation has no persisted DP values. */ @@ -413,7 +420,10 @@ IOT_API iot_client_t *iot_client_init_on_boarding_with_token(const iot_on_boardi strncpy(ob_cfg.authkey, config->authkey, sizeof(ob_cfg.authkey) - 1); strncpy(ob_cfg.product_key, config->product_key, sizeof(ob_cfg.product_key) - 1); - strncpy(ob_cfg.sw_ver, IOT_SDK_SW_VER, sizeof(ob_cfg.sw_ver) - 1); + const char *sw_ver = (config->sw_ver && config->sw_ver[0]) + ? config->sw_ver + : IOT_SDK_SW_VER; + strncpy(ob_cfg.sw_ver, sw_ver, sizeof(ob_cfg.sw_ver) - 1); strncpy(ob_cfg.pv, IOT_SDK_PV, sizeof(ob_cfg.pv) - 1); strncpy(ob_cfg.bv, IOT_SDK_BV, sizeof(ob_cfg.bv) - 1); @@ -450,6 +460,7 @@ IOT_API iot_client_t *iot_client_init_on_boarding_with_token(const iot_on_boardi client_config.cacert = config->cacert; client_config.cert_bundle_attach = config->cert_bundle_attach; client_config.message_callback = config->message_callback; + client_config.sw_ver = sw_ver; /* schema / schema_id come from the activation response. iot_client_init() * copies them and rebuilds the DP registry from the schema (dp_state is then * initialized from the schema); first activation has no persisted DP values. */ diff --git a/modules/iot-client/src/iot_config_defaults.h b/modules/iot-client/src/iot_config_defaults.h index 49b9405..76507a4 100644 --- a/modules/iot-client/src/iot_config_defaults.h +++ b/modules/iot-client/src/iot_config_defaults.h @@ -41,9 +41,15 @@ #define IOT_DEFAULT_PORT 443 +#ifndef IOT_SDK_SW_VER #define IOT_SDK_SW_VER "1.0.0" +#endif +#ifndef IOT_SDK_PV #define IOT_SDK_PV "2.3" +#endif +#ifndef IOT_SDK_BV #define IOT_SDK_BV "2.0" +#endif #define SDK_VERSION "agentic-kit_0.1.0" /** diff --git a/modules/iot-client/src/iot_ota.c b/modules/iot-client/src/iot_ota.c index 6307682..6f81d76 100644 --- a/modules/iot-client/src/iot_ota.c +++ b/modules/iot-client/src/iot_ota.c @@ -41,7 +41,7 @@ int iot_ota_report_version(iot_client_t *client, const char *sw_ver) return atop_version_update(client->pal, &req); } -int iot_ota_check_upgrade(iot_client_t *client, int channel, const char *sw_ver, +int iot_ota_check_upgrade(iot_client_t *client, int channel, iot_ota_upgrade_info_t *info) { if (client == NULL || info == NULL) { @@ -58,7 +58,6 @@ int iot_ota_check_upgrade(iot_client_t *client, int channel, const char *sw_ver, .devid = client->devid, .key = client->secret_key, .channel = channel, - .sw_ver = sw_ver, .host = host[0] ? host : NULL, .port = port, .cacert = client->cacert, diff --git a/modules/iot-client/test/iot_ota_test.c b/modules/iot-client/test/iot_ota_test.c index fd3700c..e60b040 100644 --- a/modules/iot-client/test/iot_ota_test.c +++ b/modules/iot-client/test/iot_ota_test.c @@ -196,7 +196,6 @@ static int test_upgrade_get_with_upgrade(void) .devid = TEST_DEVID, .key = TEST_SEC_KEY, .channel = 0, - .sw_ver = "1.0.0", .host = MOCK_HOST, .port = MOCK_PORT, .cacert = g_cacert,